【问题标题】: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);
  }

【问题讨论】:

    标签: html angular typescript


    【解决方案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

    【讨论】:

      猜你喜欢
      • 2012-09-04
      • 2014-10-20
      • 1970-01-01
      • 2014-05-26
      • 2021-08-12
      • 2020-07-31
      • 2017-05-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多