Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Material=> Mat-chip- Autocomplete(input) on selecting dropdown through space key

How to populate mat-chip onkeypress(spacebar) when we select mat-option by going on option through arrow key and pressing space key(32).

However, it is working fine when we select dropdownmenu by going to option through arrowkey and then pressing enter key(keycode- 13) but not working on similarly on space key(keycode -32).

Here, is stackblitz link:- https://stackblitz.com/edit/angular-ytk8qk-feaqaw?file=app/chips-autocomplete-example.html

1) How to add select dropdown option by going through
  arrowkey(not mouse) and populating selected option using spacebar(keycode- 32).

2)How to remove option from dropdown that is already populated or used.

3)Show dropdown only when user enters some charcter in input text else show 
  class="info"` text only in dropdown, when no input text is there and no 
 option in dropdown matches enter charcters in input.

Note:- The user can create chips by typing in input and then press ENTER or SPACE key (separator key) for creating chips.

chip.component.ts

export class ChipsAutocompleteExample {
  visible = true;
  selectable = true;
  removable = true;
  addOnBlur = true;
  separatorKeysCodes: number[] = [ENTER,SPACE, COMMA];
  fruitCtrl = new FormControl();
  filteredFruits: Observable<string[]>;
  fruits: string[] = ['Lemon'];
  allFruits: string[] = ['Apple', 'Lemon', 'Lime', 'Orange', 'Strawberry'];

  @ViewChild('fruitInput') fruitInput: ElementRef<HTMLInputElement>;
  @ViewChild('auto') matAutocomplete: MatAutocomplete;

  constructor() {
    this.filteredFruits = this.fruitCtrl.valueChanges.pipe(
        startWith(null),
        map((fruit: string | null) => fruit ? this._filter(fruit) : this.allFruits.slice()));
  }

  add(event: MatChipInputEvent): void {
    // Add fruit only when MatAutocomplete is not open
    // To make sure this does not conflict with OptionSelected Event
    if (!this.matAutocomplete.isOpen) {
      const input = event.input;
      const value = event.value;

      // Add our fruit
      if ((value || '').trim()) {
        this.fruits.push(value.trim());
      }

      // Reset the input value
      if (input) {
        input.value = '';
      }

      this.fruitCtrl.setValue(null);
    }
  }

  remove(fruit: string): void {
    const index = this.fruits.indexOf(fruit);

    if (index >= 0) {
      this.fruits.splice(index, 1);
    }
  }

  selected(event: MatAutocompleteSelectedEvent): void {
    this.fruits.push(event.option.viewValue);
    this.fruitInput.nativeElement.value = '';
    this.fruitCtrl.setValue(null);
  }

  private _filter(value: string): string[] {
    const filterValue = value.toLowerCase();

    return this.allFruits.filter(fruit => fruit.toLowerCase().indexOf(filterValue) === 0);
  }
}
like image 634
Manzer Avatar asked Jun 29 '26 06:06

Manzer


1 Answers

1) How to add select dropdown option by going through arrowkey(not mouse) and populating selected option using spacebar(keycode- 32).

  1. Add properties to hold the selected fruit and the currently displayed fruits (filtered ones):

    selectedFruit = -1; displayedFruits = [];

  2. After view init, subscribe to changes on keyManager to get the selected option and to changes on filtered fruits to get the filtered list and store it on displayedFruits :

ngAfterViewInit() {
  this.matAutocomplete._keyManager.change.subscribe((index) => {
    if (index >= 0) {
      this.selectedFruit = index;
    }
  })
  this.filteredFruits.subscribe((filteredFruits) => {
    this.displayedFruits = filteredFruits;
  });
}
  1. On add method, include an else clause to include the fruit and reset selectedFruit to -1:
add(event: MatChipInputEvent): void {
   // Add fruit only when MatAutocomplete is not open
   // To make sure this does not conflict with OptionSelected Event
   if (!this.matAutocomplete.isOpen) {
     // ...
   } else {
     if (this.selectedFruit >= 0) {
       this.fruits.push(this.displayedFruits[this.selectedFruit])
       this.fruitInput.nativeElement.value = '';
       this.fruitCtrl.setValue(null);
     } else if (this.fruitInput.nativeElement.value !== '' && this.displayedFruits.length === 0) {
       this.fruits.push(this.fruitInput.nativeElement.value)
       this.fruitInput.nativeElement.value = '';
       this.fruitCtrl.setValue(null);
     }
   }
   this.selectedFruit = -1;
}    

2)How to remove option from dropdown that is already populated or used.

Enhance the filter to also check for already used fruit:

private _filter(value: string): string[] {
   const filterValue = value.toLowerCase();
   return this.allFruits.filter(fruit => fruit.toLowerCase().indexOf(filterValue) === 0 && !this.fruits.find( existingFruit => existingFruit === fruit ));
}  

3)Show dropdown only when user enters some charcter in input text else show class="info"` text only in dropdown, when no input text is there and no option in dropdown matches enter charcters in input.

If I got it right, you may do this:

  1. Bind to input focus event to show autocomplete when input is focused
<input
placeholder="New fruit..."
#fruitInput
(focus)="matAutocomplete.showPanel = true"
[formControl]="fruitCtrl"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)">
  1. Modify your autocomplete template to show an extra class="info" option when no text is entered or no value matches:
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)">
  <mat-option class="info" *ngIf="displayedFruits.length === 0 || fruitInput.value === ''" disabled>Test</mat-option>
  <ng-container *ngIf="fruitInput.value !== ''">
    <mat-option *ngFor="let fruit of displayedFruits" [value]="fruit">
      {{fruit}}
    </mat-option>
  </ng-container>
</mat-autocomplete>

Working stackblitz here

like image 187
GCSDC Avatar answered Jun 30 '26 22:06

GCSDC



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!