Skip to content

Instantly share code, notes, and snippets.

@128keaton
Created April 14, 2021 18:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 128keaton/a67c3fe14d70dd3becd4628f56b18e34 to your computer and use it in GitHub Desktop.
Save 128keaton/a67c3fe14d70dd3becd4628f56b18e34 to your computer and use it in GitHub Desktop.
Material Chip List Autocomplete Fix Directive
import {AfterContentInit, ContentChild, Directive, QueryList, ViewContainerRef} from '@angular/core';
import {MatAutocompleteTrigger} from '@angular/material/autocomplete';
import {MatChip, MatChipList} from '@angular/material/chips';
/**
* This directive fixes the Material Chip List Autocomplete issue where if you click an option in the autocomplete menu,
* the panel doesn't return unless you click out and click back in again.
*
* Keaton Burleson
*/
@Directive({
selector: '[chipListAutocompleteFix]'
})
export class ChipListAutocompleteFixDirective implements AfterContentInit {
// Use ContentChild decorator to get the MatAutocomplete component and the MatAutoCompleteTrigger component
@ContentChild(MatChipList) chipList: MatChipList;
@ContentChild(MatAutocompleteTrigger, {read: MatAutocompleteTrigger}) input: MatAutocompleteTrigger;
// Keep track of the raw input inside of the MatFormField
private rawInput: HTMLInputElement;
private chipCount = 0;
/**
* Constructor
*
* @param _viewContainerRef - We need this to fetch the raw input element from inside of the MatFormField
*/
constructor(private _viewContainerRef: ViewContainerRef) {
}
/**
* This function runs after the content has been displayed.
* This is important to make sure all the DOM rendering is finished for the Material components
*/
ngAfterContentInit(): void {
if (!this.rawInput) {
// Query our input element directly
this.rawInput = this._viewContainerRef.element.nativeElement.querySelector('input');
}
// Watch for changes on the Chip List
this.chipList.chips.changes.subscribe((changes: QueryList<MatChip>) => {
const currentChipCount = changes.length;
// Check if we're adding or removing a chip to toggle input
if (currentChipCount < this.chipCount || currentChipCount > this.chipCount) {
this.toggleInput();
}
// Update chip count
this.chipCount = currentChipCount;
});
}
/**
* This function sets the search value of the autocomplete to a blank string then opens the panel again
*
* @private
*/
private toggleInput() {
if (!!this.input && !!this.rawInput) {
this.rawInput.value = '';
// NOTE: setTimeout() is required to trigger a change quickly in e DOM
setTimeout(() => this.input.openPanel(), 0);
return;
}
console.warn('You have not supplied a valid value for autocompleteInput. The fix will not work');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment