Let’s look at ourtemplate:
code/forms/app/ts/forms/demo_form_sku.ts
4 @Component({
5 selector: 'demo-form-sku', 6 directives: [FORM_DIRECTIVES], 7 template: `
8 <div class="ui raised segment">
9 <h2 class="ui header">Demo Form: Sku</h2>
10 <form #f="ngForm"
22 <button type="submit" class="ui button">Submit</button>
23 </form>
24 </div>
25 `
26 })
form&NgForm
Now things get interesting: because we injectedFORM_DIRECTIVES, that makesNgFormavailable to our view. Remember that whenever we make directives available to our view, they will get attached to any element that matches theirselector.
NgForm does something handy but non-obvious: it includes the form tag in its selector (instead of requiring you to explicitly add ngForm as an attribute). What this means is that if you inject FORM_DIRECTIVES,NgFormwill get automatically attached to any<form>tags you have in your view.
This is really useful but potentially confusing because it happens behind the scenes.
There are two important pieces of functionality thatNgFormgives us:
1. AControlGroupnamedngForm
2. A(ngSubmit)output
You can see that we use both of these in the<form>tag in our view:
code/forms/app/ts/forms/demo_form_sku.ts 10 <form #f="ngForm"
11 (ngSubmit)="onSubmit(f.value)"
First we have#f="ngForm". If you recall the#v=thingsyntax says that we want to create a local vari-able for this view (remember we’ve used this syntax before with*ngFor. As in*ngFor="#product in products").
Here we’re creating an alias tongForm, for this view, bound to the variable#f. Where didngForm come from in the first place? It came from theNgFormdirective.
And what type of object isngForm? It is aControlGroup. That means we can usefas aControlGroup in our view. And that’s exactly what we do in the(ngSubmit)output.
Astute readers might notice that I just said above thatNgFormis automatically attached to
<form>tags (because of the defaultNgFormselector), which means we don’t have to add an
ngFormattribute to useNgForm. But here we’re puttingngFormin an attribute (value) tag.
Is this a typo?
No, it’s not a typo. IfngFormwere the key of the attribute then we would be telling Angular that we want to useNgFormon this attribute. In this case, we’re usingngFormas the attribute
when we're assigning a _reference_. That is, we're saying the value of the evaluated expression ngForm should be assigned to a local template variable
f‘.
ngFormis already on this element and you can think of it as if we are “exporting” this
ControlGroupso that we can reference it elsewhere in our view.
We bind to thengSubmitaction of our form by using the syntax:(ngSubmit)="onSubmit(f.value)".
• (ngSubmit)- comes fromNgForm
• onSubmit()- will be implemented in our component definition class (below)
• f.value-fis theControlGroupthat we specified above. And.valuewill return the key/value pairs of thisControlGroup
Put it all together and that line says “when I submit the form, call onSubmit on my component instance, passing the value of the form as the arguments”.
input&NgControl
Ourinputtag has a few things we should touch on before we talk aboutNgControl:
code/forms/app/ts/forms/demo_form_sku.ts
• class="ui form"andclass="field"- these two classes are totally optional. They come from theCSS framework Semantic UI³³. I’ve added them in some of our examples just to give them a nice coat of CSS but they’re not part of Angular.
• Thelabel“for” attribute and theinput“id” attribute are to match, asper W3C standard³⁴
• We set aplaceholderof “SKU”, which is just a hint to the user for what thisinputshould say when it is blank
The NgControl directive specifies a selector of ngControl³⁵. This means we can attach it to our input tag by adding this sort of attribute: ngControl="whatever". In this case, we say:
ngControl="sku".
NgControlvs.ngControl: what’s the difference? Generally, when we use PascalCase, like
NgControl, we’re specifying the class and referring to the object as it’s defined in code.
The lower case (CamelCase), as inngControl, comes from theselectorof the directive and it’s only used in the DOM / template.
It’s also worth pointing out thatNgControlandControlare separate objects.NgControlis the directive that you use in your view, whereasControlis the object used for representing the data and validations.
It’s worth pointing out thatngControl is concretely defined in the classNgControlName
(notNgControl). Youcan find the definition here³⁶
³³http://semantic-ui.com/
³⁴http://www.w3.org/TR/WCAG20-TECHS/H44.html
³⁵https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/directives/ng_control_name.ts
³⁶https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/directives/ng_control_name.ts
NgControl creates a new Control that is automatically added to the parent ControlGroup (in this case, on the form) and then binds a DOM element to that newControl. That is, it sets up an association between theinputtag in our view and theControland the association is matched by a name, in this case"sku".
ngControlmust be used as a child ofNgForm(orNgFormModel, which we talk about below).
Don’t try to usengControlwithout anNgFormparent or you’ll have problems.