I am trying to implement in Angular2 (beta 0 with TS in Plunker) a script with two nested forms, each of which is represented by a component.
The parent component Wordthat represents the word in the fake dictionary. The children's components are the WordSense's, each of which represents the meaning of the parent word.
Both components use model-driven forms, and a child form associates its model values ββwith the formation of controls using ngModel. Thus, the parent component can easily convey its semantic sensations to the children's components, and the remaining 2-way bindings will do the rest.
Simple custom validators are attached to both forms. Among other things, I would like to disable the submit button, not only when the phrase is invalid, but also when any of its values ββis invalid. To this end, I added an isValideditable model property and code to observe changes in the perception form: whenever a change occurs, I check the form property validand set the model property accordingly. Then I could easily add a check at the level of the parent component in the view and in the code, so that I can only post messages when both forms are in order.
To support custom validation and additional logic, I switched my source code from templates to model-based forms; however, as soon as I run the refactored code, I get a few No comment about the Directive traits , and I'm not sure about their meaning.
I guess I'm missing something obvious, but I'm new here. Can anyone give a suggestion? You can find reprogramming on this plunger: http://plnkr.co/edit/v9Dj5j5opJmonxEeotcR . Here is some of them:
a) parent component:
@Component({
selector: "word",
directives: [FORM_DIRECTIVES, FORM_PROVIDERS, WordSense],
templateUrl: `
<div>
<form [ngFormModel]="wordForm"
(ngSubmit)="onSubmit(wordForm.value)"
role="form">
<div class="form-group"
[class.has-error]="!lemma.valid && lemma.touched">
<label for="lemma">lemma</label>
<input type="text" id="lemma"
maxlength="100" required spellcheck="false"
class="form-control"
placeholder="lemma"
[ngFormControl]="wordForm.controls['lemma']">
<div *ngIf="lemma.hasError('required') && lemma.touched"
class="text-danger small">lemma required</div>
<div *ngIf="lemma.hasError('lemmaValidator') && lemma.touched"
class="text-danger small">invalid lemma</div>
</div>
...
<div class="form-group">
<table class="table table-bordered">
<tbody>
<tr *ngFor="#s of senses">
<td>
<word-sense [sense]="s" [ranks]="ranks" [fields]="fields"></word-sense>
</td>
</tr>
</tbody>
</table>
</div>
...
<button type="submit"
[ngClass]="{disabled: !wordForm.valid}"
class="btn btn-primary btn-sm">save</button>
</form>
</div>
`,
inputs: [
"word"
]
})
export class Word {
private _word: IWordModel;
public set word(value: IWordModel) {
this._word = value;
this.setFormValues();
}
public get word() {
return this._word;
}
public wordForm: ControlGroup;
public lemma: Control;
public language: Control;
public class: Control;
public ranks: IPair<number>[];
public senses: ISenseViewModel[];
public fields: IFieldModel[];
constructor(private formBuilder:FormBuilder) {
this.senses = [
this.createSense()
];
this.wordForm = this.formBuilder.group({
"lemma": ["", Validators.compose([Validators.required, LemmaValidator.isValidLemma])],
"language": ["eng", Validators.required],
"class": ["s.", Validators.required],
});
this.lemma = <Control> this.wordForm.controls["lemma"];
this.language = <Control> this.wordForm.controls["language"];
this.class = <Control> this.wordForm.controls["class"];
}
}
b) child component:
@Component({
selector: "word-sense",
directives: [FORM_DIRECTIVES],
template: `
<form class="form-inline" role="form" [ngFormModel]="senseForm">
<div class="form-group"
[class.has-error]="!definitionCtl.valid">
<input type="text"
class="form-control"
placeholder="definition"
[ngFormControl]="definitionCtl"
[(ngModel)]="sense.definition">
</div>
<div class="form-group"
[class.has-error]="!yearCtl.valid">
<input type="number"
class="form-control"
placeholder="date"
[ngFormControl]="yearCtl"
[(ngModel)]="sense.year">
</div>
...
</form>
`,
inputs: [
"sense",
"ranks",
"fields"
]
})
export class WordSense {
public sense: ISenseViewModel;
public ranks: IPair<number>[];
public fields: IFieldModel[];
public field: IFieldModel;
public senseForm: ControlGroup;
public definitionCtl: Control;
public yearCtl: Control;
public rankCtl: Control;
public fieldsCtl: Control;
constructor(private formBuilder: FormBuilder) {
this.senseForm = this.formBuilder.group({
"definition": ["", Validators.required],
"year": [0, Validators.compose([Validators.required, YearValidator.isValidYear])],
"rank": [{value: 2, label: "media"}, Validators.required],
"fields": [""]
});
this.definitionCtl = <Control> this.senseForm.controls["definition"];
this.yearCtl = <Control> this.senseForm.controls["year"];
this.rankCtl = <Control> this.senseForm.controls["rank"];
this.fieldsCtl = <Control> this.senseForm.controls["fields"];
}
}