首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将嵌套表单的有效性集成到主表单中

如何将嵌套表单的有效性集成到主表单中
EN

Stack Overflow用户
提问于 2020-03-22 04:22:23
回答 1查看 20关注 0票数 0

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

总之,用户可以创建不同的部分/答案,并可以保存它们。为每个已保存的答案创建一个矩形按钮。在内部,所有这些都保存在表单中并进行验证。我使用的是ace-editor,它已经提供了将编辑器用作表单控件的功能。

来自A.ts的代码片段

代码语言:javascript
复制
  createForm() {
    this.codeEditorForm = this.fb.group({
      answer: [null, [this.validateThereIsAtleastOneSavedAnswer(this.answers),this.validateThereIsNoUnsavedAnswer(this.answers)]],
    });
  }

来自A.html的代码片段

代码语言:javascript
复制
<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

代码语言:javascript
复制
<A #a [readonlyFormStatus]="readonlyFormStatus" (answerSectionsEmitter)="handleAEvent($event)" class="form-control" formControlName="field5" [ngClass]="validateField('field5')" ></A>

我希望只有在bFormaForm都通过验证的情况下才提交bform

遵循Angular设计哲学,什么才是正确的方式?

EN

回答 1

Stack Overflow用户

发布于 2020-03-22 22:32:29

正确的方法似乎是由A实现ControlValueAccessor接口。

代码语言:javascript
复制
export class A implements OnInit, AfterViewInit,  ControlValueAccessor {
...

...
}

“有处理文本inputstextareasDefaultValueAccessor,处理select输入的SelectControlValueAccessor,还有处理checkboxes和更多内容的CheckboxControlValueAccessor。因此,对于这些UI元素,我们不需要创建值访问器,但对于自定义组件,我们需要创建一个自定义访问器。”- https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

解释--我要求formB获取A的值,并将其映射到formBfield5。但是Angular不知道A的价值是什么。对于input字段,Angular已经知道文本框的值是映射到表单控件的值。但是对于自定义组件,我们必须显式地告诉Angular自定义组件生成的映射到form字段的值是什么,这是通过实现ControlValueAccess接口来实现的。

这个接口有3个重要的方法。1) writeValue,这是一种在模型改变时告诉用户界面如何改变的方法。例如,自定义组件的UI是一个滑块,左端表示0%,右端表示100%。如果模型更改为一个值,比如10/100,那么UI需要滑到10%。更新此方法以更改UI。在我的例子中,我不需要在其中做任何事情,因为在我的例子中,数据输入方向是UI到model,而不是model to UI (我的模型不会创建需要在文本区域中填充的文本。

代码语言:javascript
复制
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)。我希望此时传播所有已保存答案的值

代码语言:javascript
复制
answers:Array<AnswerInformation>;
propagateChange = (_: any) => {};

  registerOnChange(fn) {
    console.log('registerOnchange called');
    this.propagateChange = fn;
  }

  inSaveAnswer(){
...
    this.propagateChange(this.answers);
  }

分配的值被映射到A映射到的表单域。

代码语言:javascript
复制
<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不是一个空数组,如下所示

代码语言:javascript
复制
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'
          }
        };
      }
    }

还需要实现更多的函数

代码语言:javascript
复制
registerOnTouched() {
    console.log('registerOnTouched called');
  }

  setDisabledState(isDisabled: boolean): void {
    console.log('set disabled called with value ',isDisabled);
    this.editor.setReadOnly(isDisabled);
  }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60792866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档