我有一个组件A,如下所示

总之,用户可以创建不同的部分/答案,并可以保存它们。为每个已保存的答案创建一个矩形按钮。在内部,所有这些都保存在表单中并进行验证。我使用的是ace-editor,它已经提供了将编辑器用作表单控件的功能。
来自A.ts的代码片段
createForm() {
this.codeEditorForm = this.fb.group({
answer: [null, [this.validateThereIsAtleastOneSavedAnswer(this.answers),this.validateThereIsNoUnsavedAnswer(this.answers)]],
});
}来自A.html的代码片段
<ace-editor id="editor" class="form-control" formControlName="answer" [ngClass]="validateField('answer')" [(text)]="text"></ace-editor>我想在其他组件中使用此组件作为表单控件。例如。我还有另一个组件B,它也有一个form
B.ts this.bForm = this.fb.group({ field1: null,field2: null,field3: null,Validators.required,field4: null,field5: null,//A的值映射到B field6: null }中表单的该字段,);}
B.html
<A #a [readonlyFormStatus]="readonlyFormStatus" (answerSectionsEmitter)="handleAEvent($event)" class="form-control" formControlName="field5" [ngClass]="validateField('field5')" ></A>我希望只有在bForm和aForm都通过验证的情况下才提交bform。
遵循Angular设计哲学,什么才是正确的方式?
发布于 2020-03-22 22:32:29
正确的方法似乎是由A实现ControlValueAccessor接口。
export class A implements OnInit, AfterViewInit, ControlValueAccessor {
...
...
}“有处理文本inputs和textareas的DefaultValueAccessor,处理select输入的SelectControlValueAccessor,还有处理checkboxes和更多内容的CheckboxControlValueAccessor。因此,对于这些UI元素,我们不需要创建值访问器,但对于自定义组件,我们需要创建一个自定义访问器。”- https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
解释--我要求formB获取A的值,并将其映射到formB的field5。但是Angular不知道A的价值是什么。对于input字段,Angular已经知道文本框的值是映射到表单控件的值。但是对于自定义组件,我们必须显式地告诉Angular自定义组件生成的映射到form字段的值是什么,这是通过实现ControlValueAccess接口来实现的。
这个接口有3个重要的方法。1) writeValue,这是一种在模型改变时告诉用户界面如何改变的方法。例如,自定义组件的UI是一个滑块,左端表示0%,右端表示100%。如果模型更改为一个值,比如10/100,那么UI需要滑到10%。更新此方法以更改UI。在我的例子中,我不需要在其中做任何事情,因为在我的例子中,数据输入方向是UI到model,而不是model to UI (我的模型不会创建需要在文本区域中填充的文本。
writeValue(value:any){
console.log('write value called with value ',value);
}2) registerOnChange -这与writeValue相反。每当UI更改时,模型也需要更改。在我的例子中,每当用户在文本框中写入内容时,我就想要更新我的模型。"Angular为您提供了一个函数,并要求您在组件中使用新值进行更改时调用该函数,以便它可以更新控件。“- https://netbasal.com/angular-custom-form-controls-made-easy-4f963341c8e2
在我的示例中,我希望传播更改,然后单击A的保存按钮(然后调用onSaveAnswer)。我希望此时传播所有已保存答案的值
answers:Array<AnswerInformation>;
propagateChange = (_: any) => {};
registerOnChange(fn) {
console.log('registerOnchange called');
this.propagateChange = fn;
}
inSaveAnswer(){
...
this.propagateChange(this.answers);
}分配的值被映射到A映射到的表单域。
<A #a [readonlyFormStatus]="readonlyFormStatus" (answerSectionsEmitter)="handleAEvent($event)" class="form-control" formControlName="field5" [ngClass]="validateField('field5')" ></A>field5将包含成比例的值(this.answers)。它的结构将是Array<AnswerInformation>;,即field5:Array<AnswerInformation>;
我可以添加验证field5不是一个空数组,如下所示
field5: [null, this.validateField5IsProvided]
validateField5IsProvided(control:AbstractControl) {
const f5:Array<AnswerInformation> = control.value;
if(f5){
if(f5.length !== 0){
// console.log('answer field is valid');
return null;
} else {
return {
validateAnswerIsSaved: { // check the class ShowErrorsComponent to see how validatePassword is used.
valid: false,
message: 'The field can\'t be empty. Please make sure to save the field'
}
};
}
} else {
return {
validateAnswerIsSaved: {
valid: false,
message: 'The fieldcan\'t be empty. Please make sure to save the field'
}
};
}
}还需要实现更多的函数
registerOnTouched() {
console.log('registerOnTouched called');
}
setDisabledState(isDisabled: boolean): void {
console.log('set disabled called with value ',isDisabled);
this.editor.setReadOnly(isDisabled);
}https://stackoverflow.com/questions/60792866
复制相似问题