【问题标题】:Angular 5 : How to set Validation on two drop down list having same data?Angular 5:如何在两个具有相同数据的下拉列表上设置验证?
【发布时间】:2018-11-29 14:26:00
【问题描述】:

数据(json)

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

模板(角度材质)

<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>

我有两个下拉列表包含具有多项选择的相同数据,如果我在 2017-1、2017-2(第一个下拉列表)中选择,则不应在第二个下拉列表中选择/填充此值。我是角度/材料的初学者,我应该在这里验证什么!我不知道我应该在 HTML/Type-Script 中写什么逻辑。 在此先感谢

【问题讨论】:

    标签: angular angular-material angular5


    【解决方案1】:

    有几种方法可以实现这一点...例如,只有一种方法是将数组拆分为两个,然后在第一个 mat-select 中选择一个选项时拼接第二个数组中的值。

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

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

    firstSelections: string = '';
    

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

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

    然后在从第一个 mat-select 更改选择时调用该方法并传递值。

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

    然后在您的第二个mat-select 定义选项时,使用disabled 上的属性绑定来检查选项是否包含在变量firstSelections 中,以禁用第二个列表中的选项(如果在第一个列表中选择)。

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

    堆栈闪电战

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


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

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

    根据 malbarmawi 下面的评论

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

    将 html 封装在一个模板驱动的表单中,你可以随意调用它,在这个例子中我只是称之为 myForm

    <form #myForm="ngForm">
    

    将表单传递给selectionChange上的方法

    (selectionChange)="setFirstValues(myForm)"
    

    为每个mat-selects分配名称和ngModel

    name="select1" ngModel
    

    通过ViewChild获取第二个选择的参考

    @ViewChild('select2') _select2: any
    

    设置更改时的第一个选择值并从第二个列表中拼接值(如果存在)并取消选择。

    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);
            }
          }
        }
      }
    

    【讨论】:

    • 如果我在第一个 ?? 之前选择第二个下拉菜单会怎样
    • 我认为响应式表单验证更适合处理所有验证任务
    • 那么我会说这不是原始问题的一部分:)
    • @Marshal 你做得很好,正如你所说There are several ways to accomplish this我的回答只是另一种方式
    • 好的@Marshal先生,让我试试我自己,否则我会提出新的问题,非常感谢先生!
    【解决方案2】:

    我确实建议使用反应式表单验证 (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函数是下拉值的验证登录

    模板

    <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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-19
      相关资源
      最近更新 更多