如何根据角度FormGroup中的输入字段数据可用性来按钮启用或禁用?

时间:2020-08-28 14:16:30

标签: angular typescript angular-reactive-forms form-control

我的表单输入字段是否为必填项,取决于API数据集。但是当它强制执行时,我需要禁用按钮,直到用户输入一些值为止。我是角度反应式的绝对初学者。需要一些专家帮助才能做到这一点。

------------ HTML ----------------------

 <div class="a">
      <at-card *ngIf="selectedId$|async" class="b">
        <at-detail [selectedDetail]="selectedDetailModel$|async">
        </at-detail>
        <div [formGroup]="DetailForm" class="grid grid-columns-2">
          <br />
          <mat-form-field>
            <mat-label>Comment</mat-label>
            <input matInput formControlName="comment" [type]="'text'" [required]="commentRequerd">
          </mat-form-field>
        </div>
      </at-card>
      <at-sticky-footer>
        <button *ngIf="selectedId$|async" (click)="onSubmit()">submit</button>
      </at-sticky-footer> 
</div>

------------------ component.ts ------------------

commentRequerd: boolean;

DetailForm = new FormGroup({ comment: new FormControl(), rate: new FormControl() });

ngOnInit(): void {
   inputCommentIsMandotory:boolean = <take API data about enter comment needed or not>
         
   //accroding to that input comment filed mark as requred->
   //is it requred need to check user input data to comment field -> 
   //if it avalable button is enable , else it disable
   if(inputCommentIsMandotory){
    this.commentRequerd = true;
    //when user enter data button enable , if not disable(input field empty)
    }else{
    //alwasy button enable (input comment or not)
    this.commentRequerd = false;
    }
 
  }

------------------最新更新(即使注释不是强制性的,也始终禁用按钮--------------- ---------------------

我像下面一样更改了代码。

isCommentMandatory(Reviews: ReviewModel[]): void {
  

      if (Reviews.length > 0) {
          console.log("called ...1 ");
          this.isCommentRequired = false;
          this.DetailForm = this.fb.group({
            comment: [''],
            rate: ['']
          });
        } else {
          console.log("called ...2 ");
          this.isCommentRequired = true;
          this.DetailForm = this.fb.group({
            comment: ['', Validators.required],
            rate: ['']
          });
        }
      }

并这样称呼它,

ngOnInit(): void {
  
       this.DetailModel$.pipe().subscribe((opd => {
          this.detail = opd as Detail;
          const date = this.detail?.time;
          const planDate = date !== undefined ? date : new Date();
          //according date select reviews data
          this.store.select(selectAllReviewsDetailsModel(planDate)).
            subscribe(res => this.Reviews = res);
    
          //need to call after change Details
          this.isCommentMandatory(this.Reviews);
        }));
      }

在其绑定的html模板中,

 <at-sticky-footer>
        <button *ngIf="selectedId$|async" [disabled]="!(DetailModel.valid && (DetailModel.dirty))" (click)="submit()">submit</button>
      </at-sticky-footer>

但是现在,两种情况都需要输入一些内容来启用按钮。

1 个答案:

答案 0 :(得分:1)

关于反应形式的想法是单向数据流。数据从组件流到模板;当用户处理完数据后,单击“保存”,组件将再次接管。

如果需要数据验证,则在组件中完成,如果有条件逻辑更改数据,则在组件中。如果有行为(但没有数据或验证更改),则可以将其作为模板指令。 (作为“例如”,在模板中作为指令完全可以很好地弹出“此行已更改”可视指示符作为突出显示。)

表格中的所有控件都是可观察的;这意味着您可以监视它们在组件中的更改并“做正确的事”,但是用例非常简单,以至于在设置表单时您可以做正确的事。需要注意的是,您可能要推迟构建表单,直到Http.GET返回为止;因为那是一个异步事件;这意味着将您的表单构建逻辑放在http调用的闭包中。

保存按钮

对于保存按钮,您可以使用:

<button [disabled]="!(DetailForm.touched && DetailForm.valid)">

因为DetailForm是基数FormGroup的变量名。

comment表单控件在其定义中需要一个[Validator.Required]

 this.DetailForm= this.fb.group({
      comment: ['', Validators.required]
  });

同样重要的是要注意,当您创建表单并最初从服务器获取数据以查看是否需要该注释时,可以创建一个Custom Validation

如何构造表单组和表单构建器:

感谢您的更新;基于此,我将构建component.ts的结构:

constructor(private fb: FormBuilder) { }
DetailForm: FormGroup;


ngOnInit(): void {
   const dataAvailable = //this.http.get<boolean>(s =>  s);
   if (dataAvailable) { 
     this.DetailForm = this.fb.group({ 
      comment: ['', Validators.Required]
     });
   }
   else { 
     this.DetailForm = this.fb.group({ 
      comment: [''];
     })
   }
  }
   

component.html

<div class="a">
      <at-card *ngIf="selectedId$|async" class="b">
        <at-detail [selectedDetail]="selectedDetailModel$|async">
        </at-detail>
        <div [formGroup]="DetailForm" class="grid grid-columns-2">
          <br />
          <mat-form-field>
            <mat-label>Comment</mat-label>
            <input matInput formControlName="comment" [type]="'text'">
          </mat-form-field>
        </div>
      </at-card>
      <at-sticky-footer>
        <button [disabled]="!(DetailForm.valid && (DetailForm.touched ||  DetailForm.dirty)"  (click)="onSubmit()">submit</button>
      </at-sticky-footer> 
</div>

关于touchedblurred的注释:

touched:表示控件已被激活,更改和模糊; dirty:表示该控件已被激活,更改,但尚未模糊。

您需要使用的那个取决于您的用例。