anchor.diff:     From this base we derived two new classes in `TextboxQuestion` and `DropdownQuestion` that represent Textbox and Dropdown questions. 
      The idea is that the form will be bound to specific question types and render the appropriate controls dynamically. 
      
  +   在这个基础上，我们衍生了两个新类`TextboxQuestion` 和 `DropdownQuestion`，分别代表文本框和下拉框。这么做的初衷是，表单能动态的绑定特定的问卷问题类型，并动态渲染合适的控制器。
  +   
      `TextboxQuestion` supports multiple html5 types like text, email, url etc via the `type` property.
  +   
  +   `TextboxQuestion`通过`type`属性，支持多种HTML5元素类型，比如文本、邮件、网址等。
   
   +makeExample('cb-dynamic-form/ts/app/question-textbox.ts',null,'app/question-textbox.ts')(format='.')
   
   :marked
      `DropdownQuestion` presents a list of choices in a select box.
      
  +   `DropdownQuestion`代表一个拥有一个列表可选项目的选择框。
  +   
   +makeExample('cb-dynamic-form/ts/app/question-dropdown.ts',null,'app/question-dropdown.ts')(format='.')
   
   :marked
      Next we have defined `QuestionControlService`, a simple service for transforming our questions to an ngForm control group. 
      In a nutshell, the control group consumes the metadata from the question model and allows us to specify default values and validation rules.
  -
  +   
  +   下一步，我们定义了`QuestionControlService`，一个可以把我们的问卷问题转换为ngForm控制组的服务。简而言之，这个ngForm控制组使用问卷模型的元数据，允许我们制定默认值和验证规则。
   +makeExample('cb-dynamic-form/ts/app/question-control.service.ts',null,'app/question-control.service.ts')(format='.')
   
   <a id="form-component"></a>
   :marked
      ## Question form components
  +   ## 问卷表单组件
  +   
      Now that we have defined the complete model we are ready to create components to represent the dynamic form.
  +   现在我们已经有一个已定义的完整模型，我们可以创建一个动态表单的组件。
   
   :marked
  -  `DynamicForm` is the entry point and the main container for the form. 
  +  `DynamicForm` is the entry point and the main container for the form.
  +  
  +  `DynamicForm`是我们表单的主要载体和切入口。 
   +makeTabs(
     `cb-dynamic-form/ts/app/dynamic-form.component.html,
      cb-dynamic-form/ts/app/dynamic-form.component.ts`,
  
positive.code:   We only have two types of questions at this point but we can imagine many more.
    The `ngSwitch` determines which type of question to display.
    
    In both components  we're relying on Angular's **ngFormModel** to connect the template HTML to the
    underlying control objects, populated from the question model with display and validation rules.
  
  <a id="questionnaire-metadata"></a>
  :marked
     ## Questionnaire data
  :marked
    `DynamicForm` expects the list of questions in the form of an array bound to  `@Input() questions`.
  
     The set of questions we have defined for the job application is returned from the `QuestionService`. 
     In a real app we'd retrieve these questions from storage.
     
     The key point is that we control the hero job application questions entirely through the objects returned from `QuestionService`. 
     Questionnaire maintenance is a simple matter of adding, updating, and removing objects from the `questions` array.
     
  +makeExample('cb-dynamic-form/ts/app/question.service.ts','','app/question.service.ts')  
  
  :marked
    Finally, we display an instance of the form in the `AppComponent` shell.
  
  +makeExample('cb-dynamic-form/ts/app/app.component.ts','','app.component.ts')
  
  <a id="dynamic-template"></a>
  :marked
     ## Dynamic Template
     Although in this example we're modelling a job application for heroes, there are no references to any specific hero question 
     outside the objects returned by `QuestionService`. 
     
     This is very important since it allows us to repurpose the components for any type of survey
     as long as it's compatible with our *question* object model. 
     The key is the dynamic data binding of metadata used to render the form 
     without making any hardcoded assumptions about specific questions. 
     In addition to control metadata, we are also adding validation dynamically.
  
     The *Save* button is disabled until the form is in a valid state. 
     When the form is valid, we can click *Save* and the app renders the current form values as JSON. 
     This proves that any user input is bound back to the data model.
     Saving and retrieving the data is an exercise for another time.
  
  :marked
     The final form looks like this:
  figure.image-display
     img(src="/resources/images/cookbooks/dynamic-form/dynamic-form.png" alt="Dynamic-Form")
  
  
  :marked
     [Back to top](#top)
negative.code:    especially if we'll need a great number of them, they're similar to each other, and they change frequently 
     to meet rapidly changing business and regulatory requirements.
     
     我们不可能一直觉得手动编写表单和需要的工作量和时间成正比，特别是当我们需要编写大量的表单，他们非常类似，而且他们需要随着商务和政策需求的迅速变化而变化。
     
     It may be more economical to create the forms dynamically, based on metadata that describe the business object model.
     
     基于商务对象模型里面的元数据，动态建立表单可能更加划算。
     
     In this cookbook we show how to use `ngFormModel` to dynamically render a simple form with different control types and validation.
     It's a primitive start. 
     It might evolve to support a much richer variety of questions, more graceful rendering, and superior user experience.
     All such greatness has humble beginnings.
    
     在本文中，我们会展示怎么利用`ngFormModel`动态渲染一个简单的表单， 包含不同类型控制器和验证规则。
     这是一个原始的开始，任何伟大都是从谦卑开始的。我们可以在这个基础上添加种类丰富的问卷问题，更加优美的渲染和更优越的用户体验。
     
     In our example we use a dynamic form to build an online application experience for heroes seeking employment.
     The agency is constantly tinkering with the application process.
     We can create the forms on the fly *without changing our application code*.
     
     在这个例子中，我们使用动态表单，为正在找工作的英雄们创建一个在线申请体验。中介在不断的修改申请流程。我们可以在*不修改程序*的情况下，动态即时的建立一个表格 
     
  <a id="toc"></a>
  :marked
     ## Table of contents
     ## 目录
        [问卷问题模型Question Model](#object-model)
        
        [表单组件Form Component](#form-component)
  
        [问卷元数据Questionnaire Metadata](#questionnaire-metadata)
        
        [动态模板Dynamic Template](#dynamic-template)
  
  :marked
     **See the [live example](/resources/live-examples/cb-dynamic-form/ts/plnkr.html)**.
     
     **请看[在线例子](/resources/live-examples/cb-dynamic-form/ts/plnkr.html)**.
     
  .l-main-section
  <a id="object-model"></a>
  :marked
     ## Question Model
     ## 问卷问题模型
        
     The first step is to define an object model that can describe all scenarios needed by the form functionality.
     The hero application process involves a form with a lot of questions. 
     The "question" is the most fundamental object in the model.
     
     第一步是定义一个对象模型，用来描述所有表单功能需要的场景。英雄申请流程涉及到一个有很多问卷问题的表单。问卷问题是最基础的对象模型。
  
     We have created `QuestionBase` as the most fundamental question class.
     
     下面是我们建立的非常基础的问卷问题类，名叫`QuestionBase`。
  
  +makeExample('cb-dynamic-form/ts/app/question-base.ts','','app/question-base.ts')
  
  