anchor.diff:  :marked
     - we inject the `FormBuilder` in a constructor.
   
  +  - 我们注入`FormBuilder`到构造函数中。
  +
     - we call a `buildForm` method in the `ngOnInit` [lifecycle hook method](../guide/lifecycle-hooks.html#hooks-overview)
     because that's when we'll have the hero data. We'll call it again in the `addHero` method.
  +
  +  - 我们在`ngOnInit`[生命周期钩子方法](../guide/lifecycle-hooks.html#hooks-overview)中调用`buildForm`方法，
  +  因为这正是我们拥有英雄数据的时刻。我们将在`addHero`方法中再次调用它。
  +
   .l-sub-section
     :marked
       A real app would retrieve the hero asynchronously from a data service, a task best performed in the `ngOnInit` hook.
  +
  +    真实的应用很可能从数据服务异步获取英雄，这个任务最好在`ngOnInit`生命周期钩子中进行。
   :marked
     - the `buildForm` method uses the `FormBuilder` (`fb`) to declare the form control model.
     Then it attaches the same `onValueChanged` handler (there's a one line difference) 
     to the form's `valueChanged` event and calls it immediately 
     to set error messages for the new control model.
   
  +  - `buildForm`方法使用`FormBuilder`（`fb`）来声明表单控制器模型。
  +  然后它将相同的`onValueChanged`（有一行代码不一样）处理器附加到表单的`valueChanged`事件，
  +  并立刻为新的控制器模型设置错误消息。
  +
   :marked
     #### _FormBuilder_ declaration
  -  The `FormBuilder` declaration object specifies the three controls of the sample's hero form. 
  +
  +  #### _FormBuilder_声明
  + 
  +  The `FormBuilder` declaration object specifies the three controls of the sample's hero form.
  +
  +  `FormBuilder`声明对象指定了本例英雄表单的三个控制器。 
   
     Each control spec is a control name with an array value. 
     The first array element is the current value of the corresponding hero field.
     The (optional) second value is a validator function or an array of validator functions.
  +
  +  每个控制器的设置都是控制器名字和数组值。
  +  第一个数组元素是英雄控件对应的当前值。
  +  第二个值（可选）是验证器函数或者验证器函数数组。
     
     Most of the validator functions are stock validators provided by Angular as static methods of the `Validators` class.
     Angular has stock validators that correspond to the standard HTML validation attributes.
   
  +  大多数验证器函数是Angular以`Validators`类的静态方法的形式提供的原装验证器。
  +  Angular有一些原装验证器，与标准HTML验证属性一一对应。
  +
     The `forbiddenNames` validator on the `"name"` control is a custom validator, 
     discussed in a separate [section below](#custom-validation).
   
  +  `"name"`控制器上的`forbiddenNames`验证器是自定义验证器，在下面单独的[小结](#custom-validation)有所讨论。
  +
   .l-sub-section  
     :marked
       Learn more about `FormBuilder` in a _forthcoming_ chapter on reactive forms. 
   
  +    到**即将到来**的响应式表单章，学习更多关于`FormBuilder`的知识。
   :marked
     #### Committing hero value changes
  +
  +  #### 提交英雄值的更新
     
     In two-way data binding, the user's changes flow automatically from the controls back to the data model properties.
     Reactive forms do not use data binding to update data model properties. 
     The developer decides _when and how_ to update the data model from control values.
   
  +  在双向数据绑定时，用户的修改自动从控制器流向数据模型属性。
  +  响应式表单不适用数据绑定来更新数据模型属性。
  +  开发者决定**何时**与**如何**从控制器的值更新数据模型。
  +
     This sample updates the model twice:
  +
  +  本例更新模型两次：
  +
     1. when the user submits the form
  +
  +  1. 当用户提交标单时
  +
     1. when the user chooses to add a new hero
   
  +  1. 当用户选择添加新英雄
  +
     The `onSubmit` method simply replaces the `hero` object with the combined values of the form:
  +
  +  `onSubmit`方法直接使用表单的值得合集来替换`hero`对象：
  +
   +makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','on-submit')(format='.')
   .l-sub-section
     :marked
       This example is "lucky" in that the `heroForm.value` properties _just happen_ to
       correspond _exactly_ to the hero data object properties.
  +
  +    本例非常“幸运”，因为`heroForm.value`属性**正好**与英雄数据对象属性对应。
   :marked
     The `addHero` method discards pending changes and creates a brand new `hero` model object.
  +
  +  `addHero`方法放弃未处理的变化，并创建一个崭新的`hero`模型对象。
  +
   +makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','add-hero')(format='.')
   :marked
     Then it calls `buildForm` again which replaces the previous `heroForm` control model with a new one.
     The `<form>` tag's `[formGroup]` binding refreshes the page with the new control model.
   
  +  然后它再次调用`buildForm`，用一个新对象替换了之前的`heroForm`控制器模型。
  +  `<form>`标签的`[formGroup]`绑定使用这个新的控制器模型更新页面。
  +
     Here's the complete reactive component file, compared to the two template-driven component files.
  +
  +  下面是完整的响应式表单的组件文件，与两个模板驱动组件文件对比：
   +makeTabs(
     `cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts,
      cb-form-validation/ts/app/template/hero-form-template2.component.ts, 
  
positive.code:    to the elements. Angular interprets those as well, adding validator functions to the control model.
  
     要验证用户输入，你添加[HTML验证属性](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation)到元素中。
     Angular拦截这些元素，添加验证器功能到控制模型中。
  
     Angular exposes information about the state of the controls including 
     whether the user has "touched" the control or made changes and if the control values are valid.
  
negative.code:   The validation error object typically has a property whose name is the validation key ('forbiddenName')
    and whose value is an arbitrary dictionary of values that we could insert into an error message (`{name}`).
  
    `forbiddenNameValidator`工厂函数返回配置好的验证器函数。
    该函数接受一个Angular控制器对象，并在控制器值有效时返回null，或无效时返回验证错误对象。
    验证错误对象通常有一个名为验证秘钥（`forbiddenName`）的属性。其值为一个任意词典，我们可以用来插入错误信息（`{name}`）。
  
  .l-sub-section
    :marked
      Learn more about validator functions in a _forthcoming_ chapter on custom form validation.
  
      在**即将到来**的自定义表单验证章节，学习更多关于验证器函数的知识。
  :marked
    #### Custom validation directive
  
    #### 自定义验证指令
  
    In the reactive forms component we added a configured `forbiddenNamevalidator`
    to the bottom of the `'name'` control's validator function list.
  
    在响应式表单组件中，我们在`'name'`控制器的验证函数列表的底部添加了一个配置了的`forbiddenNameValidator`。
  
  +makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.ts','name-validators', 'reactive/hero-form-reactive.component.ts (name validators)')(format='.')
  :marked
    In the template-driven component template, we add the selector (`forbiddenName`) of a custom _attribute directive_ to the name's input box
    and configured it to reject "bob".
  
    在模板驱动组件的模板中，我们在name的输入框元素中添加了自定义**属性指令**的选择器（`forbiddenName`），并配置它来拒绝“bob”。
  
  +makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.html','name-input', 'template/hero-form-template2.component.html (name input)')(format='.')
  :marked
    The corresponding `ForbiddenValidatorDirective` is a wrapper around the `forbiddenNamevalidator`.
  
    对应的`ForbiddenValidatorDirective`包装了`forbiddenNamevalidator`。
    
    Angular forms recognizes the directive's role in the validation process because the directive registers itself
    with the `NG_VALIDATORS` provider, a provider with an extensible collection of validation directives.
  
    Angular表单接受指令在验证流程中的作用，因为指令注册自己到`NG_VALIDATORS`提供商中，该提供商拥有可扩展的验证指令集。
  
  +makeExample('cb-form-validation/ts/app/shared/forbidden-name.directive.ts','directive-providers', 'shared/forbidden-name.directive.ts (providers)')(format='.')
  :marked
    The rest of the directive is unremarkable and we present it here without further comment.
  
    指令的剩余部分没有什么特殊的，所以我们将它展示在下面，不作任何注解。
  
  +makeExample('cb-form-validation/ts/app/shared/forbidden-name.directive.ts','directive', 'shared/forbidden-name.directive.ts (directive)')
  :marked
  .l-sub-section
    :marked
      See the [Attribute Directives](../guide/attribute-directives.html) chapter.
  
      参见[属性型指令](../guide/attribute-directives.html)章节。
  
  .l-main-section
  a#testing
  :marked
    ## Testing Considerations
  
    ## 测试注意事项
  
    We can write _isolated unit tests_ of validation and control logic in _Reactive Forms_.
  
    我们可以为**响应式表单**的验证器和控制器逻辑编写**孤立单元测试**。
  
    _Isolated unit tests_ probe the component class directly, independent of its
    interactions with its template, the DOM, other dependencies, or Angular itself.
  
    **孤立单元测试**直接检测组件类，与组件和它的模板的交互、DOM、其他以来和Angular本省都无关。
  
    Such tests have minimal setup, are quick to write, and easy to maintain.
    They do not require the `Angular TestBed` or asynchronous testing practices.
  
    这样的测试具有简单设置#，快速编写和容易维护的特征。它们不需要`Angular TestBed`或异步测试工序。
  
    That's not possible with _Template-driven_ forms.
    The template-driven approach relies on Angular to produce the control model and 
  