Input handling is an important part of application development. The ng-model directive provided in Angular 1 is a great way to manage input, but we think we can do better. The new Angular Forms module is easier to use and reason about than ng-model, it provides the same conveniences as ng-model, but does not have its drawbacks. In this article we will talk about the design goals for the module and show how to use for common use cases.

Optimizing for real world apps

Let's look at what a simple HelloWorld example would look like in Angular 2:
 
@Component({
  selector: 'form-example'
})
@Template({
  // we are binding the input element to the control object
  // defined in the component's class 
  inline: `<input [control]="username">Hello {{username.value}}!`,
  directives: [forms]
})
class FormExample {
  constructor() {
    this.username = new Control('World');
  }
}
 
This example is written using TypeScript 1.5 that supports type and metadata annotations, but it can be easily written in ES6 or ES5. You can find more information on annotations here. The example also uses the new template syntax that you can learn about by watching the keynote Misko and Rado gave at NgConf.
 
And, for comparison sake, here's what we'd write in Angular 1:
 
var module = angular.module("example", []);
 
module.controller("FormExample", function() {
  this.username = "World";
});
 
<div ng-controller="FormExample as ctrl">
  <input ng-model="ctrl.username"> Hello {{ctrl.username}}!
</div>
 
At the surface Angular 1 example looks simpler that what we have just done in Angular 2. Let's talk about the challenges of Angular 1 approach with real world applications. 
  • You can not unit test the form behavior without compiling the associated template. This is because the template contains part of the application behavior.
  • Though you can do dynamically generated data-driven forms in Angular 1, it is not easy and we want to enable this as a core use case for Angular 2.
  • The ng-model directive was built using a generic two-way data-binding which makes it difficult to reason about your template statically. Will go into depth on this topic in a following blog post and describe how it lets us achieve significant performance improvements.
  • There was no concept of an atomic form which could easily be validated, or reverted to original state.
Although Angular 2 uses an extra level of indirection, it grants major benefits. The control object decouples form behavior from the template, so that you can test it in isolation. Tests are simpler to write and faster to execute. 
 
Now let's look at a more complex example so that you can see some of these properties.

Forms Mental Model

In Angular 2 working with Forms is broken down to three layers. At the very bottom we can work with HTML elements. On top of that Angular 2 provides the Form Controls API which we have shown in the example above. Finally, Angular 2 will also provide a data-driven forms API which will make building large-scale forms a snap.

 
Let's look at how this extra level of indirection benefits us for more realistic examples.

Data-Driven Forms

Let's say we would like to build a form such as this:
 
 
We will have an object model of an Address which needs to be presented to the user. The requirements also include providing correct layout, labels, and error handling. We would write it like this in Angular 2. 
 
(This is proposed API, we would love to take your input on this.)
 
import {forms, required, materialDesign} from 'angular2/forms';
 
// Our model
class Address {
  street: string;
  city: string;
  state: string;
  zip: string;
  residential: boolean;
 
@Component({
  selector: 'form-example'
})
@Template({
  // Form layout is automatic from the structure
  inline: `<form [form-structure]=”form”></form>`
  directives: [forms]
})
class FormExample {
  constructor(fb: FormBuilder) {
    this.address = new Address();
 
    // defining a form structure and initializing it using 
    // the passed in model
    this.form = fb.fromModel(address, [
      // describe the model field, labels and error handling
      {field: 'street', label: 'Street', validator: required},
      {field: 'city', label: 'City', validator: required},
      {field: 'state', label: 'State', size: 2, 
              validator: required},
      {field: 'zip', label: 'Zip', size: 5, 
              validator: zipCodeValidator},
      {field: 'isResidential', type: 'checkbox', 
              label: 'Is residential'}
    }, {
      // update the model every time an input changes
      saveOnUpdate: true,
      // Allow setting different layout strategies
      layoutStrategy: materialDesign
    });
  }
}
 
function zipCodeValidator(control) {
  if (! control.value.match(/\d\d\d\d\d(-\d\d\d\d)?/)){
    return {invalidZipCode: true};
  }
}
 
The above example shows how an existing model Address can be turned into a form. The process include describing the fields, labels, and validators in a declarative way in your component. The form HTML structure will be generated automatically based on the layout strategy provided to the builder. This helps keeping consistent look & feel through the application. Finally, it is also possible to control the write through behavior, which allows atomic writes to the model. 
 
We have taken great care to ensure that the forms API is pluggable, allowing you to define custom validators, reuse web-component controls, and define layout and theme.

Form Controls

Although having data driven forms is convenient, sometimes you would like to have full control of how a form is laid out on page. Let's rebuild the same example using the lower level API, which allows you to control the HTML structure in full detail. (This works today in Angular 2 Alpha, but we are also happy to receive your input on improvements we could make.)
 
import {forms, required} from 'angular2/forms';
 
// An example of typical model
class Address {
  street: string;
  city: string;
  state: string;
  zip: string;
  residential: boolean;
 
function zipCodeValidator(control) {
  if (! control.value.match(/\d\d\d\d\d(-\d\d\d\d)?/)){
    return {invalidZipCode: true};
  }
}
 
@Component({
  selector: 'form-example'
})
@Template({
  inline: `
    // explicitly defining the template of the form 
    <form [form]=”form”>
      Street <input control="street">
      <div *if="form.hasError('street', 'required')">Required</div>
 
      City <input control="city">
      <div *if="form.hasError('city', 'required')">Required</div>
 
      State <input control="state" size="2">
      <div *if="form.hasError('state', 'required')">Required</div>
 
      Zip <input control="zip" size="5">
      <div *if="form.hasError('zip', 'invalidZipCoed')">
        Zip code is invalid
      </div>
 
      Residential <input control="isResidential" type="checkbox">
    </form> 
  `
  directives: [forms]
})
class FormExample {
  constructor(fb: FormBuilder) {
    this.address = new Address();
 
    // defining a form model 
    this.form = fb.group({
      street: [this.address.street, required],
      city: [this.address.city, required],
      state: [this.address.city, required],
      zip: [this.address.zip, zipCodeValidator],
      isResidential: [this.address.isResidential]
    });
 
    this.form.changes.forEach(() => this.form.writeTo(this.address));
  }
}
 
When using the control form API we still define the behavior of the form in the component, but the way the form is laid out is defined in the template. This allows you to implement even the most unusual forms. 

Summary

The new Angular 2 Forms module makes building forms easier than ever. It also adds benefits such as consistent look and feel for all forms in your application, easier unit testing, and more predictable behavior.
 
The API is still work in progress, we welcome any feedback. Please submit your input by filing issues or creating PRs at http://github.com/angular/angular.

Forms in Angular 2的更多相关文章

  1. [Angular] Create a custom validator for reactive forms in Angular

    Also check: directive for form validation User input validation is a core part of creating proper HT ...

  2. [Angular] Create a custom validator for template driven forms in Angular

    User input validation is a core part of creating proper HTML forms. Form validators not only help yo ...

  3. 从零开始构建 Wijmo & Angular 2 小应用

    中秋之际,Angular 团队发布 Angular 2 正式版,一款不错的图表控件Wijmo当天宣布支持 . Angular 2移除和替代了 Angular 1.X 中的 directives, co ...

  4. 来自 Thoughtram 的 Angular 2 系列资料

    Angular 2 已经正式 Release 了,Thoughtram 已经发布了一系列的文档,对 Angular 2 的各个方面进行深入的阐释和说明. 我计划逐渐将这个系列翻译出来,以便对大家学习 ...

  5. [Angular2 Form] Create and Submit an Angular 2 Form using ngForm

    Forms in Angular 2 are essentially wrappers around inputs that group the input values together into ...

  6. Wijmo Angular 2 小应用

    Wijmo & Angular 2 小应用 中秋之际,Angular 团队发布 Angular 2 正式版,一款不错的图表控件Wijmo当天宣布支持 . Angular 2移除和替代了 Ang ...

  7. [AngularJS] Isolate State Mutations in Angular Components

    Managing state is one of the hardest things to do in any application. Angular 2 tackles this problem ...

  8. 支持Angular 2的表格控件

    前端框架一直这最近几年特别火的一个话题,尤其是Angular 2拥有众多的粉丝.在2016年9月份Angular 2正式发布之后,大量的粉丝的开始投入到了Angular 2的怀抱.当然这其中也包括我. ...

  9. Angular 2的表格控件

    Angular 2的表格控件 前端框架一直这最近几年特别火的一个话题,尤其是Angular 2拥有众多的粉丝.在2016年9月份Angular 2正式发布之后,大量的粉丝的开始投入到了Angular ...

随机推荐

  1. Documentation/filesystems/sysfs.txt 文档翻译--sysfs

    sysfs - 用于导出内核对象的文件系统. 1.sysfs是一个基于ram的文件系统,最初基于ramfs. 它提供了一种方法,可以将内核数据结构,它们的属性以及它们之间的链接导出到用户空间.sysf ...

  2. oracle Union 中 ORA-12704:字符集不匹配问题的解决 .

    在使用Union all连接时,若A集合中某列为nvarchar2或nvarchar类型,而B集合中无此列,用‘ ’ 来代替是会报字符集不匹配,解决方法有两种,见下面的示例 例: select '中国 ...

  3. 写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用

    写写Django中DRF框架概述以及序列化器对象serializer的构造方法以及使用 一.了解什么是DRF DRF: Django REST framework Django REST framew ...

  4. hdu 4336 Card Collector——最值反演

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4336 点集中最早出现的元素的期望是 min ,最晚出现的元素的期望是 max :全部出现的期望就是最晚出现 ...

  5. RK3288 红外遥控器增加自定义按键

    转载请注明出处:https://www.cnblogs.com/lialong1st/p/10071557.html CPU:RK3288 系统:Android 5.1 1.在 dts 中增加红外遥控 ...

  6. 关于Fragment框架,说的够清晰了。。。

    Android4.0-Fragment框架实现方式剖析(一) 分类: Android UI 2012-09-19 18:59 14880人阅读 评论(8) 收藏 举报 android   目录(?)[ ...

  7. 面试总结之MISC(操作系统,网络,数学,软件开发,测试,工具,系统设计,算法)

    操作系统 解释堆和栈的区别. 分配在堆的内存与分配在堆栈的内存有什么不同 分配在堆的内存要手动去释放 线程与进程的区别 多线程中栈与堆是公有的还是私有的 在多线程环境下,每个线程拥有一个栈和一个程序计 ...

  8. 学习笔记之SQL / MySQL

    SQL Fiddle(在线执行SQL语句的网站) http://www.sqlfiddle.com/ MySQL https://www.mysql.com/ MySQL :: MySQL 5.7 R ...

  9. Charles 3断点篡改数据

    只是临时修改一次网络请求结果,使用重写过于麻烦.对于临时性的修改,最好使用断点. 断点功能主要修改requess和response内容,这个时候接口是在Charles代理层被拦截,还未到手机设备上. ...

  10. Lucene根据字段进行自定义搜索扩展

    最近需要对公司的产品搜索功能做一步改动,搜索到的结果首先按照是否有库存进行排序,然后再按照销量.由于库存量也是一个整数,如果直接按照库存量进行倒序排序的话,是不符合要求的,Lucene也没有支持我们这 ...