How to remove the previously selected option from a drop-down menu in a table?

前端 未结 2 850
广开言路
广开言路 2020-12-02 02:38

I am making a project on angular 7.It has a table with a column having dropdowns. The dropdown contains various languages. When a language is selected in a particular row, t

相关标签:
2条回答
  • 2020-12-02 03:15

    you can solve the problem by holding a set of selected languages and display options conditionally based on whether an option/language is selected before or not.

    create a Set to hold selected langs

    selectedLangs = new Set<string>();

    create a view query to get a list of all select elements

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

    whenever a selection is made/changed on any of the select elements re-populate the selectedLangs set

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

    whenever a field is deleted just remove that language from selectedLangs

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

    and when displaying options for a select check if it is currently selected on current select or already selected in another select *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>
    

    where isSelected is defined as

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

    here is a working demo with full source https://stackblitz.com/edit/angular-dqvvf5

    0 讨论(0)
  • 2020-12-02 03:23

    You can store the langs in an array make a function like

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

    So, you can has some like

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

    But I don't like because each change force Angular to calculate all the options. So we are going to improve the code using FormArray and an array langList, and make sure that we can not choose the same language

    First our variable and our function changed

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

    We create a formArray

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

    And in 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})
             })
          }
        })
      }
    

    See that use formArray valueChanges with pipe(startWith(null)) to create at first the langList

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

    And the demo in stackblitz

    0 讨论(0)
提交回复
热议问题