docs(forms): revise prose for form.reset (#2853)
This commit is contained in:
parent
a7525721c0
commit
434308ab1b
|
@ -36,7 +36,7 @@
|
||||||
required
|
required
|
||||||
[(ngModel)]="model.power" name="power"
|
[(ngModel)]="model.power" name="power"
|
||||||
#power="ngModel" >
|
#power="ngModel" >
|
||||||
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
|
<option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
|
||||||
</select>
|
</select>
|
||||||
<div [hidden]="power.valid || power.pristine" class="alert alert-danger">
|
<div [hidden]="power.valid || power.pristine" class="alert alert-danger">
|
||||||
Power is required
|
Power is required
|
||||||
|
@ -46,12 +46,18 @@
|
||||||
<!-- #docregion submit-button -->
|
<!-- #docregion submit-button -->
|
||||||
<button type="submit" class="btn btn-default" [disabled]="!heroForm.form.valid">Submit</button>
|
<button type="submit" class="btn btn-default" [disabled]="!heroForm.form.valid">Submit</button>
|
||||||
<!-- #enddocregion submit-button -->
|
<!-- #enddocregion submit-button -->
|
||||||
|
<!-- #docregion new-hero-button-form-reset -->
|
||||||
<!-- #docregion new-hero-button -->
|
|
||||||
<button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()">New Hero</button>
|
<button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()">New Hero</button>
|
||||||
<!-- #enddocregion new-hero-button -->
|
<!-- #enddocregion new-hero-button-form-reset -->
|
||||||
|
|
||||||
<!-- #enddocregion final -->
|
<!-- #enddocregion final -->
|
||||||
|
<i>with</i> reset
|
||||||
|
|
||||||
|
|
||||||
|
<!-- #docregion new-hero-button-no-reset -->
|
||||||
|
<button type="button" class="btn btn-default" (click)="newHero()">New Hero</button>
|
||||||
|
<!-- #enddocregion new-hero-button-no-reset -->
|
||||||
|
<i>without</i> reset
|
||||||
|
|
||||||
<!-- NOT SHOWN IN DOCS -->
|
<!-- NOT SHOWN IN DOCS -->
|
||||||
<div>
|
<div>
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -126,7 +132,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="power">Hero Power</label>
|
<label for="power">Hero Power</label>
|
||||||
<select class="form-control" id="power" required>
|
<select class="form-control" id="power" required>
|
||||||
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
|
<option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -165,7 +171,7 @@
|
||||||
<select class="form-control" id="power"
|
<select class="form-control" id="power"
|
||||||
required
|
required
|
||||||
[(ngModel)]="model.power" name="power">
|
[(ngModel)]="model.power" name="power">
|
||||||
<option *ngFor="let p of powers" [value]="p">{{p}}</option>
|
<option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -178,12 +184,12 @@
|
||||||
|
|
||||||
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
|
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
|
||||||
<hr>
|
<hr>
|
||||||
<!-- #docregion ngModel-1-->
|
<!-- #docregion ngModelName-1 -->
|
||||||
<input type="text" class="form-control" id="name"
|
<input type="text" class="form-control" id="name"
|
||||||
required
|
required
|
||||||
[(ngModel)]="model.name" name="name">
|
[(ngModel)]="model.name" name="name">
|
||||||
TODO: remove this: {{model.name}}
|
TODO: remove this: {{model.name}}
|
||||||
<!-- #enddocregion ngModel-1-->
|
<!-- #enddocregion ngModelName-1 -->
|
||||||
<hr>
|
<hr>
|
||||||
<!-- #docregion ngModel-3-->
|
<!-- #docregion ngModel-3-->
|
||||||
<input type="text" class="form-control" id="name"
|
<input type="text" class="form-control" id="name"
|
||||||
|
@ -193,16 +199,6 @@
|
||||||
TODO: remove this: {{model.name}}
|
TODO: remove this: {{model.name}}
|
||||||
<!-- #enddocregion ngModel-3-->
|
<!-- #enddocregion ngModel-3-->
|
||||||
<hr>
|
<hr>
|
||||||
<!-- #docregion form-reset -->
|
|
||||||
<button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()">New Hero</button>
|
|
||||||
<!-- #enddocregion form-reset -->
|
|
||||||
|
|
||||||
<!-- #docregion ngModelName-1 -->
|
|
||||||
<input type="text" class="form-control" id="name"
|
|
||||||
required
|
|
||||||
[(ngModel)]="model.name" name="name" >
|
|
||||||
<!-- #enddocregion ngModelName-1 -->
|
|
||||||
<hr>
|
|
||||||
<!-- #docregion ngModelName-2 -->
|
<!-- #docregion ngModelName-2 -->
|
||||||
<input type="text" class="form-control" id="name"
|
<input type="text" class="form-control" id="name"
|
||||||
required
|
required
|
||||||
|
|
|
@ -30,11 +30,9 @@ export class HeroFormComponent {
|
||||||
|
|
||||||
// #docregion final
|
// #docregion final
|
||||||
// #docregion new-hero
|
// #docregion new-hero
|
||||||
// #docregion new-hero-v1
|
|
||||||
newHero() {
|
newHero() {
|
||||||
this.model = new Hero(42, '', '');
|
this.model = new Hero(42, '', '');
|
||||||
}
|
}
|
||||||
// #enddocregion new-hero-v1
|
|
||||||
// #enddocregion new-hero
|
// #enddocregion new-hero
|
||||||
// #enddocregion final
|
// #enddocregion final
|
||||||
//////// NOT SHOWN IN DOCS ////////
|
//////// NOT SHOWN IN DOCS ////////
|
||||||
|
|
|
@ -2,7 +2,4 @@
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
// Compiles the module (asynchronously) with the runtime compiler
|
|
||||||
// which generates a compiled module factory in memory.
|
|
||||||
// Then bootstraps with that factory, targeting the browser.
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||||
|
|
|
@ -9,11 +9,11 @@ include ../_util-fns
|
||||||
It's more challenging to create a cohesive data entry experience that guides the
|
It's more challenging to create a cohesive data entry experience that guides the
|
||||||
user efficiently and effectively through the workflow behind the form.
|
user efficiently and effectively through the workflow behind the form.
|
||||||
|
|
||||||
*That* takes design skills that are, to be frank, well out of scope for this chapter.
|
*That* takes design skills that are, to be frank, well out of scope for this guide.
|
||||||
|
|
||||||
It also takes framework support for
|
It also takes framework support for
|
||||||
**two-way data binding, change tracking, validation, and error handling**
|
**two-way data binding, change tracking, validation, and error handling**
|
||||||
... which we shall cover in this chapter on Angular forms.
|
... which we shall cover in this guide on Angular forms.
|
||||||
|
|
||||||
We will build a simple form from scratch, one step at a time. Along the way we'll learn how to
|
We will build a simple form from scratch, one step at a time. Along the way we'll learn how to
|
||||||
|
|
||||||
|
@ -36,10 +36,10 @@ include ../_util-fns
|
||||||
## Template-Driven Forms
|
## Template-Driven Forms
|
||||||
|
|
||||||
Many of us will build forms by writing templates in the Angular [template syntax](./template-syntax.html) with
|
Many of us will build forms by writing templates in the Angular [template syntax](./template-syntax.html) with
|
||||||
the form-specific directives and techniques described in this chapter.
|
the form-specific directives and techniques described in this guide.
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
That's not the only way to create a form but it's the way we'll cover in this chapter.
|
That's not the only way to create a form but it's the way we'll cover in this guide.
|
||||||
:marked
|
:marked
|
||||||
We can build almost any form we need with an Angular template — login forms, contact forms ... pretty much any business forms.
|
We can build almost any form we need with an Angular template — login forms, contact forms ... pretty much any business forms.
|
||||||
We can lay out the controls creatively, bind them to data, specify validation rules and display validation errors,
|
We can lay out the controls creatively, bind them to data, specify validation rules and display validation errors,
|
||||||
|
@ -122,9 +122,9 @@ code-example(format="").
|
||||||
:marked
|
:marked
|
||||||
## Create a Form component
|
## Create a Form component
|
||||||
|
|
||||||
An Angular form has two parts: an HTML-based template and a code-based Component to handle data and user interactions.
|
An Angular form has two parts: an HTML-based _template_ and a component _class_
|
||||||
|
to handle data and user interactions programmatically.
|
||||||
We begin with the Component because it states, in brief, what the Hero editor can do.
|
We begin with the class because it states, in brief, what the hero editor can do.
|
||||||
|
|
||||||
Create a new file called `hero-form.component.ts` and give it the following definition:
|
Create a new file called `hero-form.component.ts` and give it the following definition:
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ code-example(format="").
|
||||||
:marked
|
:marked
|
||||||
There’s nothing special about this component, nothing form-specific, nothing to distinguish it from any component we've written before.
|
There’s nothing special about this component, nothing form-specific, nothing to distinguish it from any component we've written before.
|
||||||
|
|
||||||
Understanding this component requires only the Angular concepts we’ve learned in previous chapters
|
Understanding this component requires only the Angular concepts we’ve learned in previous guides
|
||||||
|
|
||||||
1. We import the `Component` decorator from the Angular library as we usually do.
|
1. We import the `Component` decorator from the Angular library as we usually do.
|
||||||
|
|
||||||
|
@ -153,17 +153,19 @@ code-example(format="").
|
||||||
1. We threw in a `diagnostic` property at the end to return a JSON representation of our model.
|
1. We threw in a `diagnostic` property at the end to return a JSON representation of our model.
|
||||||
It'll help us see what we're doing during our development; we've left ourselves a cleanup note to discard it later.
|
It'll help us see what we're doing during our development; we've left ourselves a cleanup note to discard it later.
|
||||||
|
|
||||||
Why don't we write the template inline in the component file as we often do
|
### Why the separate template file?
|
||||||
elsewhere in the Developer Guide?
|
|
||||||
|
Why don't we write the template inline in the component file as we often do elsewhere?
|
||||||
|
|
||||||
There is no “right” answer for all occasions. We like inline templates when they are short.
|
There is no “right” answer for all occasions. We like inline templates when they are short.
|
||||||
Most form templates won't be short. TypeScript and JavaScript files generally aren't the best place to
|
Most form templates won't be short. TypeScript and JavaScript files generally aren't the best place to
|
||||||
write (or read) large stretches of HTML and few editors are much help with files that have a mix of HTML and code.
|
write (or read) large stretches of HTML and few editors are much help with files that have a mix of HTML and code.
|
||||||
We also like short files with a clear and obvious purpose like this one.
|
We also like short files with a clear and obvious purpose like this one.
|
||||||
|
|
||||||
We made a good choice to put the HTML template elsewhere.
|
Form templates tend to be quite large even when displaying a small number of fields
|
||||||
We'll write that template in a moment. Before we do, we'll take a step back
|
so it's usually best to put the HTML template in a separate file.
|
||||||
and revise the `app.module.ts` and `app.component.ts` to make use of our new `HeroFormComponent`.
|
We'll write that template file in a moment. Before we do, we'll take a step back
|
||||||
|
and revise the `app.module.ts` and `app.component.ts` to make use of the new `HeroFormComponent`.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -193,7 +195,7 @@ code-example(format="").
|
||||||
|
|
||||||
.alert.is-important
|
.alert.is-important
|
||||||
:marked
|
:marked
|
||||||
If a component, directive, or pipe belongs to a module in the `imports` array, _DON'T_ declare it in the `declarations` array.
|
If a component, directive, or pipe belongs to a module in the `imports` array, _DON'T_ re-declare it in the `declarations` array.
|
||||||
If you wrote it and it should belong to this module, _DO_ declare it in the `declarations` array.
|
If you wrote it and it should belong to this module, _DO_ declare it in the `declarations` array.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
|
@ -208,9 +210,8 @@ code-example(format="").
|
||||||
:marked
|
:marked
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
There is only one change:
|
There is only one change.
|
||||||
|
The `template` is simply the new element tag identified by the component's `selector` property.
|
||||||
1. The `template` is simply the new element tag identified by the component's `selector` property.
|
|
||||||
This will display the hero form when the application component is loaded.
|
This will display the hero form when the application component is loaded.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
|
@ -234,8 +235,7 @@ code-example(format="").
|
||||||
|
|
||||||
The `container`, `form-group`, `form-control`, and `btn` classes
|
The `container`, `form-group`, `form-control`, and `btn` classes
|
||||||
come from [Twitter Bootstrap](http://getbootstrap.com/css/). Purely cosmetic.
|
come from [Twitter Bootstrap](http://getbootstrap.com/css/). Purely cosmetic.
|
||||||
We're using Bootstrap to gussy up our form.
|
We're using Bootstrap to give the form a little style!
|
||||||
Hey, what's a form without a little style!
|
|
||||||
|
|
||||||
.callout.is-important
|
.callout.is-important
|
||||||
header Angular Forms Do Not Require A Style Library
|
header Angular Forms Do Not Require A Style Library
|
||||||
|
@ -262,27 +262,27 @@ ol
|
||||||
|
|
||||||
We'll add a `select` to our
|
We'll add a `select` to our
|
||||||
form and bind the options to the `powers` list using `ngFor`,
|
form and bind the options to the `powers` list using `ngFor`,
|
||||||
a technique we might have seen before in the [Displaying Data](./displaying-data.html) chapter.
|
a technique seen previously in the [Displaying Data](./displaying-data.html) guide.
|
||||||
|
|
||||||
Add the following HTML *immediately below* the *Alter Ego* group.
|
Add the following HTML *immediately below* the *Alter Ego* group.
|
||||||
+makeExample('forms/ts/app/hero-form.component.html', 'powers', 'app/hero-form.component.html (excerpt)')(format=".")
|
+makeExample('forms/ts/app/hero-form.component.html', 'powers', 'app/hero-form.component.html (excerpt)')(format=".")
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
We are repeating the `<options>` tag for each power in the list of Powers.
|
We are repeating the `<options>` tag for each power in the list of Powers.
|
||||||
The `p` template input variable is a different power in each iteration;
|
The `pow` template input variable is a different power in each iteration;
|
||||||
we display its name using the interpolation syntax with the double-curly-braces.
|
we display its name using the interpolation syntax with the double-curly-braces.
|
||||||
|
|
||||||
<a id="ngModel"></a>
|
<a id="ngModel"></a>
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Two-way data binding with **ngModel**
|
## Two-way data binding with **_ngModel_**
|
||||||
Running the app right now would be disappointing.
|
Running the app right now would be disappointing.
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src="/resources/images/devguide/forms/hero-form-3.png" width="400px" alt="Early form with no binding")
|
img(src="/resources/images/devguide/forms/hero-form-3.png" width="400px" alt="Early form with no binding")
|
||||||
:marked
|
:marked
|
||||||
We don't see hero data because we are not binding to the `Hero` yet.
|
We don't see hero data because we are not binding to the `Hero` yet.
|
||||||
We know how to do that from earlier chapters.
|
We know how to do that from earlier guides.
|
||||||
[Displaying Data](./displaying-data.html) taught us Property Binding.
|
[Displaying Data](./displaying-data.html) taught us Property Binding.
|
||||||
[User Input](./user-input.html) showed us how to listen for DOM events with an
|
[User Input](./user-input.html) showed us how to listen for DOM events with an
|
||||||
Event Binding and how to update a component property with the displayed value.
|
Event Binding and how to update a component property with the displayed value.
|
||||||
|
@ -295,7 +295,7 @@ figure.image-display
|
||||||
|
|
||||||
Find the `<input>` tag for the "Name" and update it like this
|
Find the `<input>` tag for the "Name" and update it like this
|
||||||
|
|
||||||
+makeExample('forms/ts/app/hero-form.component.html', 'ngModel-1','app/hero-form.component.html (excerpt)')(format=".")
|
+makeExample('forms/ts/app/hero-form.component.html', 'ngModelName-1','app/hero-form.component.html (excerpt)')(format=".")
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
|
@ -324,13 +324,13 @@ figure.image-display
|
||||||
:marked
|
:marked
|
||||||
Internally Angular creates `FormControls` and registers them with an `NgForm` directive that Angular
|
Internally Angular creates `FormControls` and registers them with an `NgForm` directive that Angular
|
||||||
attached to the `<form>` tag. Each `FormControl` is registered under the name we assigned to the `name` attribute.
|
attached to the `<form>` tag. Each `FormControl` is registered under the name we assigned to the `name` attribute.
|
||||||
We'll talk about `NgForm` [later in this chapter](#ngForm).
|
We'll talk about `NgForm` [later in this guide](#ngForm).
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Let's add similar `[(ngModel)]` bindings and `name` attributes to *Alter Ego* and *Hero Power*.
|
Let's add similar `[(ngModel)]` bindings and `name` attributes to *Alter Ego* and *Hero Power*.
|
||||||
We'll ditch the input box binding message
|
We'll ditch the input box binding message
|
||||||
and add a new binding at the top to the component's `diagnostic` property.
|
and add a new binding at the top to the component's `diagnostic` property.
|
||||||
Then we can confirm that two-way data binding works *for the entire Hero model*.
|
Then we can confirm that two-way data binding works *for the entire hero model*.
|
||||||
|
|
||||||
After revision the core of our form should have three `[(ngModel)]` bindings and `name` attributes that
|
After revision the core of our form should have three `[(ngModel)]` bindings and `name` attributes that
|
||||||
look much like this:
|
look much like this:
|
||||||
|
@ -344,7 +344,7 @@ figure.image-display
|
||||||
- Each input element has a `name` property that is required by Angular Forms to register the control with the form.
|
- Each input element has a `name` property that is required by Angular Forms to register the control with the form.
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
If we ran the app right now and changed every Hero model property, the form might display like this:
|
If we ran the app right now and changed every hero model property, the form might display like this:
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src="/resources/images/devguide/forms/ng-model-in-action-2.png" width="400px" alt="ngModel in super action")
|
img(src="/resources/images/devguide/forms/ng-model-in-action-2.png" width="400px" alt="ngModel in super action")
|
||||||
:marked
|
:marked
|
||||||
|
@ -355,7 +355,7 @@ figure.image-display
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
### Inside [(ngModel)]
|
### Inside _[(ngModel)]_
|
||||||
*This section is an optional deep dive into [(ngModel)]. Not interested? Skip ahead!*
|
*This section is an optional deep dive into [(ngModel)]. Not interested? Skip ahead!*
|
||||||
|
|
||||||
The punctuation in the binding syntax, <span style="font-family:courier"><b>[()]</b></span>, is a good clue to what's going on.
|
The punctuation in the binding syntax, <span style="font-family:courier"><b>[()]</b></span>, is a good clue to what's going on.
|
||||||
|
@ -394,11 +394,11 @@ figure.image-display
|
||||||
the event handling such as debounce or throttle the key strokes.
|
the event handling such as debounce or throttle the key strokes.
|
||||||
|
|
||||||
Learn more about `NgModel` and other template syntax in the
|
Learn more about `NgModel` and other template syntax in the
|
||||||
[Template Syntax](./template-syntax.html) chapter.
|
[Template Syntax](./template-syntax.html) guide.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Track change-state and validity with **ngModel**
|
## Track change-state and validity with **_ngModel_**
|
||||||
|
|
||||||
A form isn't just about data binding. We'd also like to know the state of the controls on our form.
|
A form isn't just about data binding. We'd also like to know the state of the controls on our form.
|
||||||
|
|
||||||
|
@ -509,7 +509,7 @@ figure.image-display
|
||||||
Now we can control visibility of the "name" error message by binding properties of the `name` control to the message `<div>` element's `hidden` property.
|
Now we can control visibility of the "name" error message by binding properties of the `name` control to the message `<div>` element's `hidden` property.
|
||||||
+makeExample('forms/ts/app/hero-form.component.html',
|
+makeExample('forms/ts/app/hero-form.component.html',
|
||||||
'hidden-error-msg',
|
'hidden-error-msg',
|
||||||
'app/hero-form.component.html (excerpt)')
|
'app/hero-form.component.html (excerpt)')(format='.')
|
||||||
:marked
|
:marked
|
||||||
In this example, we hide the message when the control is valid or pristine;
|
In this example, we hide the message when the control is valid or pristine;
|
||||||
pristine means the user hasn't changed the value since it was displayed in this form.
|
pristine means the user hasn't changed the value since it was displayed in this form.
|
||||||
|
@ -523,7 +523,7 @@ figure.image-display
|
||||||
Hiding the message while the control is "pristine" achieves that goal.
|
Hiding the message while the control is "pristine" achieves that goal.
|
||||||
We'll see the significance of this choice when we [add a new hero](#new-hero) to the form.
|
We'll see the significance of this choice when we [add a new hero](#new-hero) to the form.
|
||||||
|
|
||||||
The Hero *Alter Ego* is optional so we can leave that be.
|
The hero *Alter Ego* is optional so we can leave that be.
|
||||||
|
|
||||||
Hero *Power* selection is required.
|
Hero *Power* selection is required.
|
||||||
We can add the same kind of error handling to the `<select>` if we want
|
We can add the same kind of error handling to the `<select>` if we want
|
||||||
|
@ -536,14 +536,14 @@ figure.image-display
|
||||||
:marked
|
:marked
|
||||||
## Add a hero and reset the form
|
## Add a hero and reset the form
|
||||||
We'd like to add a new hero in this form.
|
We'd like to add a new hero in this form.
|
||||||
We place a "New Hero" button at the bottom of the form and bind its click event to a component method.
|
We place a "New Hero" button at the bottom of the form and bind its click event to a `newHero` component method.
|
||||||
+makeExample('forms/ts/app/hero-form.component.html',
|
+makeExample('forms/ts/app/hero-form.component.html',
|
||||||
'new-hero-button',
|
'new-hero-button-no-reset',
|
||||||
'app/hero-form.component.html (New Hero button)')
|
'app/hero-form.component.html (New Hero button)')
|
||||||
:marked
|
:marked
|
||||||
+makeExample('forms/ts/app/hero-form.component.ts',
|
+makeExample('forms/ts/app/hero-form.component.ts',
|
||||||
'new-hero-v1',
|
'new-hero',
|
||||||
'app/hero-form.component.ts (New Hero method - v1)')(format=".")
|
'app/hero-form.component.ts (New Hero method)')(format=".")
|
||||||
:marked
|
:marked
|
||||||
Run the application again, click the *New Hero* button, and the form clears.
|
Run the application again, click the *New Hero* button, and the form clears.
|
||||||
The *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
|
The *required* bars to the left of the input box are red, indicating invalid `name` and `power` properties.
|
||||||
|
@ -551,28 +551,26 @@ figure.image-display
|
||||||
The error messages are hidden because the form is pristine; we haven't changed anything yet.
|
The error messages are hidden because the form is pristine; we haven't changed anything yet.
|
||||||
|
|
||||||
Enter a name and click *New Hero* again.
|
Enter a name and click *New Hero* again.
|
||||||
This time we see an error message! Why? We don't want that when we display a new (empty) hero.
|
The app displays a **_Name is required_** error message!
|
||||||
|
We don't want error messages when we create a new (empty) hero.
|
||||||
|
Why are we getting one now?
|
||||||
|
|
||||||
Inspecting the element in the browser tools reveals that the *name* input box is no longer pristine.
|
Inspecting the element in the browser tools reveals that the *name* input box is _no longer pristine_.
|
||||||
Replacing the hero *did not restore the pristine state* of the control.
|
The form remembers that we entered a name before clicking *New Hero*.
|
||||||
.l-sub-section
|
Replacing the hero object *did not restore the pristine state* of the form controls.
|
||||||
:marked
|
|
||||||
Upon reflection, we realize that Angular cannot distinguish between
|
We have to clear all of the flags imperatively which we can do
|
||||||
replacing the entire hero and clearing the `name` property programmatically.
|
by calling the form's `reset()` method after calling the `newHero()` method.
|
||||||
Angular makes no assumptions and leaves the control in its current, dirty state.
|
|
||||||
:marked
|
|
||||||
We'll have to reset the form controls.
|
|
||||||
We call the `reset()` method of the form after calling the `newHero()` method.
|
|
||||||
+makeExample('forms/ts/app/hero-form.component.html',
|
+makeExample('forms/ts/app/hero-form.component.html',
|
||||||
'form-reset',
|
'new-hero-button-form-reset',
|
||||||
'app/hero-form.component.html (Reset the form)')
|
'app/hero-form.component.html (Reset the form)')
|
||||||
:marked
|
:marked
|
||||||
This will reset the `heroForm` and its status by clicking "New Hero".
|
Now clicking "New Hero" both resets the form and its control flags.
|
||||||
:marked
|
:marked
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Submit the form with **ngSubmit**
|
## Submit the form with **_ngSubmit_**
|
||||||
The user should be able to submit this form after filling it in.
|
The user should be able to submit this form after filling it in.
|
||||||
The Submit button at the bottom of the form
|
The Submit button at the bottom of the form
|
||||||
does nothing on its own but it will
|
does nothing on its own but it will
|
||||||
|
@ -591,7 +589,7 @@ figure.image-display
|
||||||
<a id="ngForm"></a>
|
<a id="ngForm"></a>
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
### The NgForm directive
|
### The _NgForm_ directive
|
||||||
What `NgForm` directive? We didn't add an [NgForm](../api/forms/index/NgForm-directive.html) directive!
|
What `NgForm` directive? We didn't add an [NgForm](../api/forms/index/NgForm-directive.html) directive!
|
||||||
|
|
||||||
Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically.
|
Angular did. Angular creates and attaches an `NgForm` directive to the `<form>` tag automatically.
|
||||||
|
@ -629,7 +627,7 @@ figure.image-display
|
||||||
jazzing it up won't teach us anything new about forms.
|
jazzing it up won't teach us anything new about forms.
|
||||||
But this is an opportunity to exercise some of our newly won
|
But this is an opportunity to exercise some of our newly won
|
||||||
binding skills.
|
binding skills.
|
||||||
If you're not interested, you can skip to the chapter's conclusion
|
If you're not interested, you can skip to the guide's conclusion
|
||||||
and not miss a thing.
|
and not miss a thing.
|
||||||
:marked
|
:marked
|
||||||
Let's do something more strikingly visual.
|
Let's do something more strikingly visual.
|
||||||
|
@ -670,7 +668,7 @@ figure.image-display
|
||||||
:marked
|
:marked
|
||||||
## Conclusion
|
## Conclusion
|
||||||
|
|
||||||
The Angular form techniques discussed in this chapter take
|
The Angular form techniques discussed in this guide take
|
||||||
advantage of the following framework features to provide support for data modification, validation and more:
|
advantage of the following framework features to provide support for data modification, validation and more:
|
||||||
|
|
||||||
- An Angular HTML form template.
|
- An Angular HTML form template.
|
||||||
|
|
Loading…
Reference in New Issue