Angular 5:如何对两个具有相同数据的下拉列表设置验证?

Angular 5 : How to set Validation on two drop down list having same data?

数据(json)

{
  "time": [
    "2017-1",
    "2017-2",
    "2017-3",
    "2017-4",
    "2017-5",
    ....
  ]
}

模板(Angular Material)

<mat-tab label="Recomandation Setting">
      <div class="row">
        <div class="col-md-4">
          <mat-form-field>
            <mat-select placeholder="Select Year/Week" class="DropDownYear" multiple>
              <mat-option *ngFor="let time1 of resYearData.time" [value]="time1">{{time1}}</mat-option>
            </mat-select>
          </mat-form-field>
        </div>
      </div>
      <div class="row">
        <div class="col-md-4">
          <mat-form-field>
            <mat-select placeholder="Select Year/Week" class="DropDownYear" multiple>
              <mat-option *ngFor="let time2 of resYearData.time" [value]="time2">{{time2}}</mat-option>
            </mat-select>
          </mat-form-field>
          <button mat-raised-button color="primary" (click)='toggle()'>View</button>
        </div>
      </div>
</mat-tab>

我有两个下拉列表包含具有多个 selection 的相同数据,如果我在 2017-1、2017-2(第一个下拉列表)上 select 那么这个值应该不是 selected/populated 在第二个下拉列表中。我是 angular/Material 的初学者,我应该在此处进行验证!我不知道我应该在 HTML/Type-Script 中写什么逻辑。 提前致谢

有几种方法可以做到这一点...例如,只有一种方法是将数组分成两部分,然后在第一个选项中 selected 时拼接第二个数组的值mat-select.

  • 您也可以只禁用第二个列表中的选项 select 在第一个 mat-select 编辑...这将是我的场景 将在本示例中使用。

创建组件变量以存储来自第一个 mat-select

的 select 离子
firstSelections: string = '';

创建方法以在该变量内设置第一个 selection 值

setFirstValues(values) {
    this.firstSelections = values;
  }

然后在第一个 mat-select 的 selection 变化上调用该方法并传递值。

<mat-select #select1 placeholder="Select Year/Week" class="DropDownYear" multiple (selectionChange)="setFirstValues($event.value)">

然后在你的第二个 mat-select 定义选项时使用 属性 绑定 disabled 来检查选项是否包含在变量 firstSelections 中以禁用第二个选项列出如果 selected 在第一个。

<mat-option *ngFor="let time2 of resYearData.time" [value]="time2" [disabled]="firstSelections.includes(time2)">{{time2}}</mat-option>

Stackblitz

https://stackblitz.com/edit/angular-rc5vwq?embed=1&file=app/select-overview-example.html


如果您需要从第二个列表中物理删除选项,您将需要探索将每个 mat-select... 拆分 resYearData 到两个单独的数组中,然后删除值来自第一个 mat-select.

的 selection 上的第二个数组
  • 概念相同,但不是分配 selection 到禁用比较的变量,你只需删除 setFirstValues() 方法中第二个数组的值。

根据 malbarmawi 在下面的评论

我已经修改了 stackblitz 以解决如果有人首先从第二个列表中 selects 的问题,方法是从第二个列表中删除 selection 然后禁用。

将 html 包装在模板驱动的表单中,您可以随意命名它,在本例中我只是将其命名为 myForm

<form #myForm="ngForm">

selectionChange

上将表单传递给您的方法
(selectionChange)="setFirstValues(myForm)"

为每个 mat-selects

分配名称和 ngModel
name="select1" ngModel

通过 ViewChild

获取对第二个 select 的引用
@ViewChild('select2') _select2: any

设置第一个 selection 值更改和拼接来自第二个列表的值(如果存在)和 deselect.

setFirstValues(form) {
    this.firstSelections = form.value.select1
    const secondSelectionsValues = this._select2.value.slice();
    for (var i = 0; i < secondSelectionsValues.length; i++) {
      if (this.firstSelections.includes(secondSelectionsValues[i])) {
        secondSelectionsValues.splice(i, 1)
        this._select2.writeValue(secondSelectionsValues);
      }
    }
  }

修订

如果 this._select2.value 不存在,添加空检查以防止 运行 的逻辑。

setFirstValues(form) {
    this.firstSelections = form.value.select1
    if (this._select2.value) {
      const secondSelectionsValues = this._select2.value.slice();
      for (var i = secondSelectionsValues.length - 1; i >= 0; i--) {
        if (this.firstSelections.includes(secondSelectionsValues[i])) {
          secondSelectionsValues.splice(i, 1)
          this._select2.writeValue(secondSelectionsValues);
        }
      }
    }
  }

我确实建议使用反应式表单验证 (FormGroup),它更简洁,并且您可以通过 brnifetate 显示验证错误,禁用基于表单验证的保存按钮

组件

 form: FormGroup;
  constructor(fb: FormBuilder) {
    let dropDownValueValidation = function (frm: FormGroup) {
      const firstValue: string[] = frm.get('first').value || [];
      const secondValue: string[] = frm.get('second').value || [];
      if (secondValue.length > 0 && firstValue.length > 0) {
        if (secondValue.some(v => firstValue.indexOf(v) !== -1)) {
          return { 'invalid': 'you can\'t use first element selection' }
        }
      } else {
        return null;
      }
    }

    this.form = fb.group({
      first: [],
      second: []
    }, { validator: dropDownValueValidation })
  }


  logValues() {
    console.log(this.form.value)
  }

dropDownValueValidation function is the validation login for the dropdown values

模板

<div [formGroup]="form">
<mat-form-field>
    <mat-select formControlName="first" placeholder="Select Year/Week" class="DropDownYear" multiple >
        <mat-option *ngFor="let time1 of resYearData.time" [value]="time1">{{time1}}</mat-option>
    </mat-select>
</mat-form-field>

<div class="col-md-4">
    <mat-form-field>
        <mat-select formControlName="second" placeholder="Select Year/Week" class="DropDownYear" multiple>
            <mat-option *ngFor="let time2 of resYearData.time" [value]="time2" >{{time2}}</mat-option>
        </mat-select>
    </mat-form-field>
</div>
<button mat-raised-button color="primary" [disabled]="form.invalid" (click)='logValues()'>View</button>
</div>
<br>
Form Validation => {{form.errors | json}}

stackblitz demo