父组件是Word,它表示假字典中的单词.子组件是WordSense,每个组件代表父词的意义.
两个组件都使用模型驱动的表单,子表单绑定其模型的值以使用ngModel形成控件.通过这种方式,父组件可以轻松地将其单词的感官传递给子组件,其余的是双向绑定.
简单的自定义验证器附加到两个表单.除其他事项外,我不仅要在单词表单无效时禁用提交按钮,还要在其任何感知无效时禁用.为此,我向正在编辑的模型添加了一个isValid属性,并在代码中添加了感知形式的变化:每当发生更改时,我都会检查表单的有效属性并相应地设置模型的属性.然后,我可以轻松地在视图和代码中的父组件级别添加一个检查,这样我只有在两个表单都正常时才能发布.
为了支持自定义验证和其他逻辑,我将初始代码从基于模板的表单切换到基于模型的表单;然而,一旦我启动重构代码,我就会发现几个No Directive注释发现错误,而且我不确定它们的含义.
可能我错过了一些明显的东西,但我在这里是个新手.谁能提出建议?你可以在这个plunker找到一个repro:http://plnkr.co/edit/v9Dj5j5opJmonxEeotcR.这里有一些基本的代码:
a)父组件:
@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; } // ... // form 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() ]; // ... // build the form this.wordForm = this.formBuilder.group({ "lemma": ["",Validators.compose([Validators.required,LemmaValidator.isValidLemma])],"language": ["eng",Validators.required],"class": ["s.",}); this.lemma = <Control> this.wordForm.controls["lemma"]; this.language = <Control> this.wordForm.controls["language"]; this.class = <Control> this.wordForm.controls["class"]; // ... } }
b)子组件:
@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 { // model being edited public sense: ISenseviewmodel; // lookup data public ranks: IPair<number>[]; public fields: IFieldModel[]; public field: IFieldModel; // form 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": ["","year": [0,YearValidator.isValidYear])],"rank": [{value: 2,label: "media"},"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"]; } // ... }
解决方法
这样做,您现在有以下错误:
No Directive annotation found on FormBuilder
实际上,问题是您将FORM_PROVIDERS设置为组件的directives属性.所以它试图使用提供者作为指令,但它们不是……
@Component({ selector: "word",<----- templateUrl: ` <div> (...) ` }) export class ...
@Component({ selector: "word",<----- templateUrl: ` <div> (...) ` }) export class ...
另一个问题是您使用templateUrl而不是Word组件的模板:
@Component({ selector: "word",templateUrl: ` <---------- ` (...)
您应该使用此代替:
@Component({ selector: "word",template: ` <---------- ` (...)
这是重构的plunkr:http://plnkr.co/edit/x0d5oiW1J9C2JrJG8NdT?p=preview.
希望它能帮到你,蒂埃里