translate: form-validation to line 486

This commit is contained in:
Zhimin YE 2016-10-19 17:01:51 +01:00
parent fb4aa6a7a0
commit 13a3074d6c
1 changed files with 185 additions and 2 deletions

View File

@ -91,44 +91,76 @@ a#template1
:marked
Note the following:
请注意一下几点:
- The `<input>` element carries the HTML validation attributes: `required`, `minlength`, and `maxlength`.
- `<input>`元素具有HTML验证属性`required`、`minlength`、和 `maxlength`。
- We set the `name` attribute of the input box to `"name"` so Angular can track this input element and associate it
with an Angular form control called `name` in its internal control model.
- 我们设置输入框的`name`属性为`"name"`这样Angular可以跟踪这个输入元素并将其内部控制器模型的一个名为`name`的Angular表单控制关联起来。
- We use the `[(ngModel)]` directive to two-way data bind the input box to the `hero.name` property.
- 我们使用`[(ngModel)]`指令,将输入框双向数据绑定到`hero.name`属性。
- We set a template variable (`#name`) to the value `"ngModel"` (always `ngModel`).
This gives us a reference to the Angular `NgModel` directive
associated with this control that we can use _in the template_
to check for control states such as `valid` and `dirty`.
- 我们将模板变量(`#name`)赋值为`"ngModel"` (总是 `ngModel`)。
它为我们提供了与这个控制器关联的Angular `NgModel`指令的引用,我们在模板中使用它,以检查控制器状态,比如`valid`和`dirty`。
- The `*ngIf` on `<div>` element reveals a set of nested message `divs` but only if there are "name" errors and
the control is either `dirty` or `touched`.
- `<div>`元素的`*ngIf`揭露了一套嵌套消息`divs`但是只在有“name”错误和控制器为`dirty`或者`touched`。
- Each nested `<div>` can present a custom message for one of the possible validation errors.
We've prepared messages for `required`, `minlength`, and `maxlength`.
- 每个嵌套的`<div>`为其中一个可能出现的验证错误显示一条自定义消息。我们已经为`required`、`minlength`、和 `maxlength`准备了消息。
The full template repeats this kind of layout for each data entry control on the form.
整个模板为表单上的每种数据输入控制器重复这种布局。
.l-sub-section
:marked
#### Why check _dirty_ and _touched_?
### 为何检查**dirty**和**touched**
We shouldn't show errors for a new hero before the user has had a chance to edit the value.
The checks for `dirty` and `touched` prevent premature display of errors.
当用户创建一个新英雄时,在还没有机会输入之前,我们不应该显示任何错误。
检查`dirty`和`touched`防止了这种过早的错误显示。
Learn about `dirty` and `touched` in the [Forms](../guide/forms.html) chapter.
参见[表单](../guide/forms.html)章,学习关于`dirty`和`touched`的知识。
:marked
The component class manages the hero model used in the data binding
as well as other code to support the view.
组件类管理用于数据绑定的英雄模型,它还有其他支持视图的代码。
+makeExample('cb-form-validation/ts/app/template/hero-form-template1.component.ts','class','template/hero-form-template1.component.ts (class)')
:marked
Use this template-driven validation technique when working with static forms with simple, standard validation rules.
在处理简单的、拥有标准验证规则的静态表单时,使用这种模板驱动验证方法。
Here are the complete files for the first version of `HeroFormTemplateCompononent` in the template-driven approach:
下面是第一个版本的使用模板驱动方法的`HeroFormTemplateComponent`
+makeTabs(
`cb-form-validation/ts/app/template/hero-form-template1.component.html,
cb-form-validation/ts/app/template/hero-form-template1.component.ts`,
@ -141,21 +173,36 @@ a#template2
:marked
## Template-Driven Forms with validation messages in code
## 验证消息在代码中的模板驱动表单
While the layout is straightforward,
there are obvious shortcomings with the way we handle validation messages:
虽然布局很直观,但是我们处理验证消息的方法有明显的缺陷:
* It takes a lot of HTML to represent all possible error conditions.
This gets out of hand when there are many controls and many validation rules.
* 它使用了很多HTML来表现所有可能出现的错误情况。
如果有太多控制器和太多验证规则,我们就失去了控制。
* We're not fond of so much JavaScript logic in HTML.
* 我们不喜欢在HTML里面插入这么多JavaScript。
* The messages are static strings, hard-coded into the template.
We often require dynamic messages that we should shape in code.
* 这些消息是静态的字符串,被硬编码到模板中。我们通常要求在代码中可以塑造的动态消息。
We can move the logic and the messages into the component with a few changes to
the template and component.
只需要对模板和组件做出一些修改,我们可以将逻辑和消息移到组件中。
Here's the hero name again, excerpted from the revised template ("Template 2"), next to the original version:
下面也是关于英雄名字的控制器,从修改后的模板("Template 2")中抽取出来,与原来的版本相比:
+makeTabs(
`cb-form-validation/ts/app/template/hero-form-template2.component.html,
cb-form-validation/ts/app/template/hero-form-template1.component.html`,
@ -165,46 +212,87 @@ a#template2
:marked
The `<input>` element HTML is almost the same. There are noteworthy differences:
- The hard-code error message `<divs>` are gone.
`<input>`元素的HTML几乎一样。但是下列有值得注意的区别
- The hard-code error message `<div>` are gone.
- 硬编码的错误消息`<div>`消失了。
- There's a new attribute, `forbiddenName`, that is actually a custom validation directive.
It invalidates the control if the user enters "bob" anywhere in the name ([try it](#live-example)).
We discuss [custom validation directives](#custom-validation) later in this cookbook.
- 添加了一个新属性`forbiddenName`,它实际上是一个自定义验证指令。
如果用户名字中的任何地方输入“bob”该指令变将控制器标记为无效[试试](#live-example))。
我们在本烹饪书后面介绍了[自定义验证指令](#custom-validation)。
- The `#name` template variable is gone because we no longer refer to the Angular control for this element.
- 模板变量`#name`消失了因为我们不再需要为这个元素引用Angular控制器。
- Binding to the new `formErrors.name` property is sufficent to display all name validation error messages.
- 绑定到新的`formErrors.name`属性,就可以处理所有名字验证错误信息了。
#### Component class
#### 组件类
The original component code stays the same.
We _added_ new code to acquire the Angular form control and compose error messages.
原来的组件代码还是一样。我们**添加**了新的代码来获取Angular表单控制器和撰写错误信息。
The first step is to acquire the form control that Angular created from the template by querying for it.
第一步是获取Angular通过查询模板而生成的表单控制器。
Look back at the top of the component template where we set the
`#heroForm` template variable in the `<form>` element:
回头看组件模板顶部,我们在`<form>`元素中设置`#heroForm`模板变量:
+makeExample('cb-form-validation/ts/app/template/hero-form-template1.component.html','form-tag','template/hero-form-template1.component.html (form tag)')(format='.')
:marked
The `heroForm` variable is a reference to the control model that Angular derived from the template.
We tell Angular to inject that model into the component class's `currentForm` property using a `@ViewChild` query:
`heroFrom`变量是Angular从模板衍生出来的控制模型的引用。
我们利用`@ViewChild`来告诉Angular注入这个模型到组件类的`currentForm`属性:
+makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.ts','view-child','template/hero-form-template2.component.ts (heroForm)')(format='.')
:marked
Some observations:
一些细节:
- Angular `@ViewChild` queries for a template variable when you pass it
the name of that variable as a string (`'heroForm'` in this case).
- Angular的`@ViewChild`使用传入的模板变量的字符串名字(这里是`'heroForm'`),来查询对应的模板变量。
- The `heroForm` object changes several times during the life of the component, most notably when we add a new hero.
We'll have to re-inspect it periodically.
- `heroForm`对象在组件的生命周期内变化了好几次,最值得注意的是当我们添加一个新英雄时的变化。我们必须定期重新检测它。
- Angular calls the `ngAfterViewChecked` [lifecycle hook method](../guide/lifecycle-hooks.html#afterview)
when anything changes in the view.
That's the right time to see if there's a new `heroForm` object.
- 当视图有任何变化时Angular调用`ngAfterViewChecked`[生命周期钩子方法](../guide/lifecycle-hooks.html#afterview)。这是查看是否有新`heroForm`对象的最佳时机。
- When there _is_ a new `heroForm` model, we subscribe to its `valueChanged` _Observable_ property.
- 当出现新`heroForm`模型时,我们订阅它的`valueChanged`**可观察**属性。
The `onValueChanged` handler looks for validation errors after every user keystroke.
`onValueChanged`处理器在每次用户键入后查找验证错误。
+makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.ts','handler','template/hero-form-template2.component.ts (handler)')(format='.')
:marked
@ -212,96 +300,191 @@ a#template2
The `data` object passed into the handler contains the current element values.
The handler ignores them. Instead, it iterates over the fields of the component's `formErrors` object.
`onValueChanged`处理器拦截用户数据输入。
包含当前元素值得`data`对象被传入处理器。
处理器忽略它们。相反,它迭代组件的`formErrors`对象。
The `formErrors` is a dictionary of the hero fields that have validation rules and their current error messages.
Only two hero properties have validation rules, `name` and `power`.
The messages are empty strings when the hero data are valid.
`formErrors`是一个词典,包含了拥有验证规则和当前错误消息的英雄控件。
只有两个英雄属性有验证规则,`name`和`power`。
当英雄数据有效时,这些消息的值为空字符串。
For each field, the handler
对于每个控件,这个处理器:
- clears the prior error message if any
- acquires the field's corresponding Angular form control
- 如果有之前的错误信息,清楚它们
- acquires the field's corresponding Angular form control
- 获取控件对应的Angular表单控制器
- if such a control exists _and_ its been changed ("dirty") _and_ its invalid ...
- 如果这样的控制器存在并且它被更新“dirty”**以及**它无效...
- the handler composes a consolidated error message for all of the control's errors.
- 处理器便为所有控制器的错误合成一条错误消息。
We'll need some error messages of course, a set for each validated property, one message per validation rule:
很显然,我们需要一些错误消息,每个验证的属性都需要一套,每个验证规则需要一条消息:
+makeExample('cb-form-validation/ts/app/template/hero-form-template2.component.ts','messages','template/hero-form-template2.component.ts (messages)')(format='.')
:marked
Now every time the user makes a change, the `onValueChanged` handler checks for validation errors and produces messages accordingly.
现在,每次用户作出变化时,`onValueChanged`处理器检查验证错误并按情况发出错误消息。
### Is this an improvement?
### 这是增强吗?
Clearly the template got substantially smaller while the component code got substantially larger.
It's not easy to see the benefit when there are just three fields and only two of them have validation rules.
很显然,模板变得小多了,组件代码变得大多了。当只有三个控件并且其中只有两个有验证规则时,我们很难看出好处。
Consider what happens as we increase the number of validated fields and rules.
In general, HTML is harder to read and maintain than code.
The initial template was already large and threatening to get rapidly worse as we add more validation message `<divs>`.
假设增加需要验证的控件和规则后会怎么样。
通常HTML比代码更难阅读和维护。
初始的模板已经很大了,如果我们添加更多验证消息`<div>`,它会迅速变得更大。
After moving the validation messaging to the component,
the template grows more slowly and proportionally.
Each field has approximately the same number of lines no matter its number of validation rules.
The component also grows proportionally, at the rate of one line per validated field
and one line per validation message.
将验证消息移到组件后,模板的增长变得更加缓慢,幅度也小一些。
不管有多少个验证规则,每个控件的行数是差不多的。
组件也按比例增长,每增加一个控件增加一行,每个验证消息一行。
Both trends are manageable.
两条线容易维护。
Now that the messages are in code, we have more flexibility. We can compose messages more intelligently.
We can refactor the messages out of the component, perhaps to a service class that retrieves them from the server.
In short, there are more opportunities to improve message handling now that text and logic have moved from template to code.
现在消息在代码中,我们有更多的灵活度。我们更加智能的撰写消息。
我们可以将消息重构出组件,比如到一个服务类,从服务端获取消息。
简而言之,有很多机会增强消息处理,因为文本和逻辑都已经从模板移到代码中。
### _FormModule_ and template-driven forms
### _FormModule_ 和模板驱动表单
Angular has two different forms modules &mdash; `FormsModule` and `ReactiveFormsModule` &mdash;
that correspond with the two approaches to form development.
Both modules come from the same `@angular/forms` library package.
Angular有两种不同的表单模块 - `FormsModule`和`ReactiveFormsModule` - 它们与表单开发的两种方法对应。
两种模块都从同一个`@angular/forms`库。
We've been reviewing the "Template-driven" approach which requires the `FormsModule`
Here's how we imported it in the `HeroFormTemplateModule`.
我们一直在探讨**模板驱动**方法,它需要`FormsModule`。下面是如何在`HeroFormTemplateModule`中导入它:
+makeExample('cb-form-validation/ts/app/template/hero-form-template.module.ts','','template/hero-form-template.module.ts')(format='.')
.l-sub-section
:marked
We haven't talked about the `SharedModule` or its `SubmittedComponent` which appears at the bottom of every
form template in this cookbook.
我们还没有讲`SharedModule`或者它的`SubmittedComponent`,它们出现在本烹饪书的每一个表单模板中。
They're not germane to the validation story. Look at the [live example](#live-example) if you're interested.
它们与表单验证没有紧密的关系。如果你感兴趣,参见[在线例子](#live-example)。
.l-main-section
a#reactive
:marked
## Reactive Forms
## 响应式表单
In the template-driven approach, you markup the template with form elements, validation attributes,
and `ng...` directives from the Angular `FormsModule`.
At runtime, Angular interprets the template and derives its _form control model_.
在模板驱动方法中你在模板中标出表单元素、验证属性和Angular`FormsModule`中的`ng...`指令。
在运行时间Angular解释模板并从**表单控制器模型**衍生它。
**Reactive Forms** takes a different approach.
You create the form control model in code. You write the template with form elements
and`form...` directives from the Angular `ReactiveFormsModule`.
At runtime, Angular binds the template elements to your control model based on your instructions.
**响应式表单**采用不同的方法。
你在代码中创建表单控制器模型并用表单元素和来自Angular `ReactiveFormsModule`中的`form...`指令来编写模板。
在运行时间Angular根据你的指示绑定模板元素到你的控制器模型。
This approach requires a bit more effort. *You have to write the control model and manage it*.
这个方法需要做一些额外的工作。*你必须编写并管理控制器模型**
In return, you can
作为回报,你可以:
* add, change, and remove validation functions on the fly
* 随时添加、修改和删除验证功能
* manipulate the control model dynamically from within the component
* 在组件内动态操纵控制器模型
* [test](#testing) validation and control logic with isolated unit tests.
* 使用孤立单元测试来[测试](#testing)验证和控制器逻辑
The third cookbook sample re-writes the hero form in _reactive forms_ style.
第三个烹饪书例子用**响应式表单**风格重新编写英雄表格。
### Switch to the _ReactiveFormsModule_
### 切换到_ReactiveFormsModule_
The reactive forms classes and directives come from the Angular `ReactiveFormsModule`, not the `FormsModule`.
The application module for the "Reactive Forms" feature in this sample looks like this:
响应式表单类和指令来自于Angular的`ReactiveFormsModule`,不是`FormsModule`。
本例中,应用模块的“响应式表单”特性是这样的:
+makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.module.ts','','app/reactive/hero-form-reactive.module.ts')(format='.')
:marked
The "Reactive Forms" feature module and component are in the `app/reactive` folder.
Let's focus on the `HeroFormReactiveComponent` there, starting with its template.
“响应式表单”特性模块和组件在`app/reactive`目录。
让我们关注那里的`HeroFormReactiveComponent`,先看它的模板。
### Component template
## 组件模板
We begin by changing the `<form>` tag so that it binds the Angular `formGroup` directive in the template
to the `heroForm` property in the component class.
The `heroForm` is the control model that the component class builds and maintains.
我们先修改`<form>`标签让Angular的`formGroup`指令绑定到组件类的`heroForm`属性。
`heroForm`是组件类创建和维护的控制器模型。
+makeExample('cb-form-validation/ts/app/reactive/hero-form-reactive.component.html','form-tag')(format='.')
:marked
Then we modify the template HTML elements to match the _reactive forms_ style.