如何从表格的下拉菜单中删除先前选择的选项?

Posted

技术标签:

【中文标题】如何从表格的下拉菜单中删除先前选择的选项?【英文标题】:How to remove the previously selected option from a drop-down menu in a table? 【发布时间】:2019-11-15 04:45:31 【问题描述】:

我正在 Angular 7 上制作一个项目。它有一个带有下拉列表的表格。下拉列表包含各种语言。在特定行中选择一种语言时,它不应出现在后续行的下拉列表中。我该怎么做?

我尝试使用 splice() 从数组中删除选定的语言。但是当它删除对象时,它也不会显示在下拉列表中。

下面是html-(它是定义下拉列表的表格的行,并且该行是动态的)

 <tr *ngFor="let field of fieldArray;let i = index">
  <td><button class="btn" (click)="deleteFieldValue(i)"><i class="fa fa-trash"></i></button></td>
  <td class="select">
    <select #selectLang (change)="selected(selectLang.value,i)">
      <option value="undefined" disabled>Select Language</option>
      <option *ngFor="let lang of languageList" value=lang.name [ngValue]="lang.name">lang.name</option>
    </select>
  </td>
  <td>
    <input id="fileUpload" name="fileUpload" type="file" name="upload_file" (change)=onFileChange($event)>
  </td>
</tr>

以下是打字稿代码-

languageList = ['name': "Dothraki",'name': "Japanese", 
'name':"German",'name':"French",'name': "Spanish", 'name': 
"Russian", 'name': "Italian"];
  selectedLang;
  optionLang:string;
  fieldArray: Array<any> = [];
  newAttribute: any = ;
  fileUploadName: any;
  selected(lang:string,index:number)
    console.log(lang);

    // this.languageList.splice(index, 1);
    for(let i =0; i< this.languageList.length; i++) 
      if(this.languageList[i]['name'] === lang) 
        this.languageList.splice(i,1);
        break;
      
    
  
  addFieldValue() 
    this.fieldArray.push("hg");
    this.newAttribute = ;
  
  deleteFieldValue(index: number) 
    this.fieldArray.splice(index, 1);

  openFileBrowser(event:any)
    event.preventDefault();
    let element: HTMLElement = document.getElementById('fileUpload') as 
HTMLElement;
    element.click();
  

  onFileChange(event:any)
    let files = event.target.files;
    this.fileUploadName = files[0].name;
    console.log(files);
  

【问题讨论】:

【参考方案1】:

您可以通过持有一组选定的语言并根据之前是否选择选项/语言有条件地显示选项来解决问题。

创建一个Set 来保存选定的语言

selectedLangs = new Set&lt;string&gt;();

创建视图查询以获取所有选择元素的列表

@ViewChildren("selectLang") langSelects: QueryList<ElementRef<HTMLSelectElement>>;

每当对任何选择元素进行选择/更改时,都会重新填充selectedLangs

  selected() 
    this.selectedLangs.clear();
    this.langSelects.forEach(ls => 
      const selectedVal = ls.nativeElement.value;
      if (selectedVal && selectedVal !== "undefined") this.selectedLangs.add(selectedVal);
    );
 

每当删除一个字段时,只需从 selectedLangs 中删除该语言

  deleteFieldValue(index: number, lang: string) 
    this.selectedLangs.delete(lang);
    this.fieldArray.splice(index, 1);
  

当显示一个选择的选项时,检查它当前是在当前选择中选择的还是已经在另一个选择中选择*ngIf="selectLang.value === lang.name || !isSelected(lang.name)"

<ng-container *ngFor="let lang of languageList" >
  <option *ngIf="selectLang.value === lang.name || !isSelected(lang.name)" value=lang.name [ngValue]="lang.name">
      lang.name
  </option>
</ng-container>

isSelected 定义为

  isSelected(lang: string) 
    return this.selectedLangs.has(lang);
  

这是一个完整源代码的工作演示https://stackblitz.com/edit/angular-dqvvf5

【讨论】:

这有帮助,但它显示“错误:ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:'ngIf:true'。当前值:'ngIf:false'。”当我将 formcontrolname 放入选择中时。如果您使用 formcontrolname @ysf 将此代码转换为 formarray 反应形式,这会很有帮助吗【参考方案2】:

您可以将语言存储在一个数组中,制作一个类似的函数

  lang = []; //define the array
  getLang(i, languageList) 
    return i == 0 ? languageList :
      this.getLang(i - 1, languageList.filter(x => x.name != this.lang[i-1]))
  

所以,你可以有一些喜欢

<div *ngFor="let a of languageList;let i=index">
    <select  [(ngModel)]="lang[i]">
      <option value="undefined" disabled>Select Language</option>
      <option *ngFor="let lang of getLang(i,languageList)" 
          [value]="lang.name" >lang.name</option>
    </select>
</div>

但我不喜欢,因为每次更改都会迫使 Angular 计算所有选项。所以我们将使用FormArray和数组langList来改进代码,并确保我们不能选择相同的语言

首先我们的变量和函数发生了变化

  langList=[];
  getLangForFormArray(i, languageList) 
    return i == 0 ? languageList :
      this.getLang(i - 1, this.langList[i-1].filter(x => x.name != this.formArray.value[i-1]))
  

我们创建一个formArray

  formArray=new FormArray(this.languageList.map(()=>new FormControl(null)))

在 ngOnInit 中

  ngOnInit()
  
    this.formArray.valueChanges.pipe(startWith(null)).subscribe(()=>
      //create the langList array
      for (let i=0;i<this.languageList.length;i++)
         this.langList[i]=this.getLangForFormArray(i,this.languageList)

      //check no repeat values
      if (value)
      
         value.forEach((x,index)=>
         if (this.formArray.value.findIndex(v=>v==x)!=index)
             this.formArray.at(index).setValue(null,emitEvent:false)
         )
      
    )
  

首先看到使用 formArray valueChanges 和 pipe(startWith(null)) 来创建 langList

.html

<div *ngFor="let control of formArray.controls;let i=index">
    <select [formControl]="control">
      <option value="null" disabled>Select Language</option>
      <option *ngFor="let lang of langList[i]" 
          [value]="lang.name" >lang.name</option>
    </select>
</div>

还有stackblitz中的demo

【讨论】:

以上是关于如何从表格的下拉菜单中删除先前选择的选项?的主要内容,如果未能解决你的问题,请参考以下文章

禁用先前选择的下拉选项,检查文本和 id 值

MFC中如何做出一个下拉菜单并且做出不同的选项?

C# combox 设置显示下拉菜单的第一项,如图。还有下拉选项的索引怎么回事,所索引为零是菜单的第一个选项

请教Excel如何去除下拉菜单空白区域的问题,空白区域有公式。

当用户从下拉菜单中选择选项时,如何从数据库中打印记录?动态程序

如何设置下拉菜单的长度,?