【问题标题】:Mutually exclusive options in AngularAngular 中的互斥选项
【发布时间】:2018-02-04 16:23:40
【问题描述】:

让我试着解释一下我的情况......

我有一个包含FormArray<form>。每个FormArray 组都有“食物”control,每个组都是<select>

所有选择都由单个array填充。

我想要实现的是:

每个选择的选项必须是唯一选择的......换句话说, FormArray 中的结果必须仅包含 unique 元素。


我的实际代码:

HTML:

<form [formGroup]="formGroup">
  <div>
    <button mat-raised-button color="primary" type="button" (click)="addItem()">
      <mat-icon>add</mat-icon>Add food
    </button>
  </div>
  <ng-container
    formArrayName="items"
    *ngFor="let item of formArray.controls; index as i"
  >
    <mat-card>
      <mat-card-title>
        <h3>Item nº {{ i + 1 }}</h3>
        <button
          mat-mini-fab
          color="warn"
          matTooltip="Remove"
          type="button"
          (click)="removeItem(i)"
        >
          <mat-icon>delete</mat-icon>
        </button>
      </mat-card-title>

      <mat-card-content [formGroupName]="i">
        <mat-select
          formControlName="food"
          name="food"
          placeholder="Favorite food"
        >
          <mat-option
            [value]="food.value"
            *ngFor="let food of foods"
          >
            {{ food.viewValue }}
          </mat-option>
        </mat-select>
      </mat-card-content>
    </mat-card>
  </ng-container>
</form>

组件:

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'select-overview-example',
  templateUrl: 'select-overview-example.html',
})
export class SelectOverviewExample {
  readonly foods: readonly Food[] = [
    { value: 'steak-0', viewValue: 'Steak' },
    { value: 'pizza-1', viewValue: 'Pizza' },
    { value: 'tacos-2', viewValue: 'Tacos' }
  ];
  readonly formArray = this.formBuilder.array([]);
  readonly formGroup = this.formBuilder.group({
    items: this.formArray
  });
  
  constructor(private readonly formBuilder: FormBuilder) {}
  
  addItem(): void {
    this.formArray.push(
      this.formBuilder.group({
        food: ''
      })
    )
  }
  
  removeItem(index: number): void {
    this.formArray.removeAt(index);
  }
}

我想知道实现这一目标的最佳选择。

到目前为止,我认为有 3 个选项:

1 - 禁用已在另一个&lt;select&gt; 中选择的选项;

2 - 创建一个自定义验证器并告诉用户他不能在 2 个或更多选择中选择一个选项。

3 - 从其他选择中完全删除 selected 选项。

我更喜欢第一个。选项,但是我找不到这样做的方法。有人可以告诉我一些开始吗?我希望这个问题足够清楚。

这是demo

【问题讨论】:

标签: angular angular-reactive-forms angular-material2 angular-forms


【解决方案1】:

只需构建我自己的解决方案:

我创建了一个方法来检查它是否应该被禁用:

isOptionDisabled(value: string, index: number): boolean {
  const foodsFormArray = this.formArray.value as readonly FoodFormGroup[];
  const foundIndex = foodsFormArray.findIndex(({ food }) => food === value);

  return foundIndex !== -1 && foundIndex !== index;
}

所以,在模板中...

...
<mat-option
  [disabled]="isOptionDisabled(food.value, i)"
  [value]="food.value"
  *ngFor="let food of foods"
...

DEMO

这不是最佳解决方案吗?也许...如果您有其他选择,请告诉我。

【讨论】:

    【解决方案2】:

    这可以通过订阅控件的valueChanges来实现,

    this.formGroup.controls['items'].valueChanges.subscribe(
       d=>{
           _.remove(this.foods,(item)=>{return item=== d[0].food})
     })
    

    在订阅中,从数组中移除元素。

    删除时,再次将对象推入数组,如下所示,

    removeItem(index: number) {
          this.foods.push(this.formArray.controls[index].controls["food"].value);
          this.formArray.removeAt(index);
    }
    

    UPDATED PLUNKER FOR LIVE DEMO

    【讨论】:

    • 感谢您的回答,但它不起作用。每当您选择一个选项时,它都会从当前选择中删除,因此您有一个空白选择。看看你的笨蛋..
    • @dev_054 你能清楚地解释我的代码中的差距吗?
    猜你喜欢
    • 2018-06-20
    • 2018-01-02
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 2013-03-12
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    相关资源
    最近更新 更多