Open ffredsh opened 6 years ago
The stackblitz does not appear to be set up correctly. The <input>
needs a matChipInputFor
directive rather than a matInput
directive (see: https://material.angular.io/components/chips/overview). I also don't think setting a formControl
on the input will add chips to the chipList
@tinayuangao is there a way to put a formControl
on the mat-chip-list
itself so they can update the chips by changing the formControl
value?
Oops, how embarrassing! I had to recreate the stackblitz after accidentally navigating away from the first one. I've updated the stackblitz.
I'm not looking to add chips through form control, I just want to be able to have the input respond to FormControl's setValue calls. Right now, if you have both a mat-chip-list AND autocomplete, the input view will not respond to setValue. Try commenting out the mat-chip-list OR the autocomplete, you'll see that the input will once again respond to setValue and show a counter going up.
Hmm interesting. I made an expanded example that shows this working with other combinations of input and autocomplete but failing for chips + autocomplete. It must be some kind of bad interaction between the two components.
@crisbeto as well, as owner of autocomplete
I'm doing same, chips + autocomplete + Input. The purpose of a combination is allowing a user to select multiple options with searching using APIs (remote data).
Searching will populate autocomplete options and after selecting autocomplete option, I'm populating chip list selected items.
After selection of autocomplete item, value clearance is not working.
<mat-form-field class="demo-chip-list">
<mat-chip-list #tolist>
<mat-chip *ngFor="let user of selectedUser" [selectable]="true" [removable]="true">
{{user.name}}
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<input matInput placeholder="New user..." type="text"
name="to" formControlName="to"
[matChipInputFor]="tolist"
(matChipInputTokenEnd)="add($event)" />
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event)" [displayWith]="displayFn">
<mat-option *ngFor="let user of users" [value]="user">
{{ user.name }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
selected(event){
this.selectedUser.push(event.option.value);
this.composeForm.controls['to'].setValue('abc');
}
Hi,
I have the same issue. This causes the following behavior when using the chips with autocomplete example (https://stackblitz.com/angular/beoyjxqloag?file=app%2Fchips-autocomplete-example.ts):
Thanks, Marc
As a temporary fox for this you can do:
<mat-form-field *ngIf="formGroup.get('categories') as control">
<mat-chip-list #categoriesChipList>
<mat-chip *ngFor="let selected of control.controls; let i = index;" removable="true"
(removed)="removeCategory(i)">
...
<input #categoryInput matInput formControlName="categoryInput"
...
<mat-hint *ngIf="formGroup.get('categoryInput').touched && control.invalid; else showLabel">
<mat-error>At least 1 category is required</mat-error>
</mat-hint>
<ng-template #showLabel>
<mat-hint>Categories</mat-hint>
</ng-template>
This will show the error over the hint at least. The control is not underlined in red though..
Having the same issue here. Combining autocomplete and chips on a formField and using control.setValue(...)
won't do anything.
Interestingly enough, valueChanges
got triggered with the value that is used in control.setValue(...)
(but is not displayed)
Having the same issue here. Combining autocomplete and chips on a formField and using
control.setValue(...)
won't do anything.Interestingly enough,
valueChanges
got triggered with the value that is used incontrol.setValue(...)
(but is not displayed)
Check your displayFn, if not send more code maybe I can help, I've been searching for bug for hours and finally found it maybe I can help you too
Same issue here. Any solution?
The only workaround I found is to set the value manually:
<mat-form-field>
<mat-chip-list #chipList>
<mat-chip *ngFor="let value of selected">{{value}}</mat-chip>
<input #inputRef
placeholder="Input Name"
[formControl]="inputFormControl"
[matAutocomplete]="autocomplete"
[matChipInputFor]="chipList"
(matChipInputTokenEnd)="add($event.value)">
</mat-chip-list>
<mat-autocomplete #autocomplete (optionSelected)="add($event.option.viewValue)">
<mat-option *ngFor="let value of values" value="{{value}}">{{value}}</mat-option>
</mat-autocomplete>
</mat-form-field>
inputFormControl = new FormControl('');
@ViewChild('inputRef', {static: true}) inputRef: ElementRef<HTMLInputElement>;
add(value: string): void {
this.selected.push(value);
this.inputControl.setValue('');
this.inputRef.nativeElement.value = ''; // Won't work without this line
}
@tim-kuteev thank you it works. I had initially just put some javascript like (HTMLInputElement document.getElementById('id')).value = ' '; (the tag characters <> were not showing the htmlinputelement so I had to remove them in the comment).
But you do it the right way with viewchild in this case. Thanks ! :)
I'm also encountering this issue. Generally it feels like the chip list and autocomplete do not work together perfectly. For example selected chips do not work in this scenario. Even if the chip has [selected]="true"
it will simply not display as selected.
Any update on this issue?
I got the same issue , here's my code
<mat-form-field class="example-chip-list">
<mat-chip-list #chipList>
<mat-chip
*ngFor="let primer of element.selectedPrimers"
[selectable]="true"
[removable]="true"
(removed)="removePrimer(element,primer)">
{{primer.name}}
<mat-icon matChipRemove *ngIf="true">cancel</mat-icon>
</mat-chip>
<input
placeholder="选择载体..."
[formControl]="primeSearchControl"
[matAutocomplete]="auto"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="false"
/>
<mat-icon matSuffix (click)="endSelectPrimer(inplace)">done_all</mat-icon>
</mat-chip-list>
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="primerSelected(element,
$event)">
<mat-option *ngFor="let primer of primerOptions" [value]="primer">
{{primer.name}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
the
this.primeSearchControl.setValue('', {emitEvent: false})
in primerSelected
method not work
As a workaround it is possible to define your own copy of the [matAutoComplete]
directive, which doesn't provide NG_VALUE_ACCESSOR
.
import { Directive, Input } from "@angular/core";
import { MatAutocomplete, MatAutocompleteTrigger } from "@angular/material/autocomplete";
/**
* This hack is necessary because `MatAutocompleteTrigger` provides `NG_VALUE_ACCESSOR`,
* which doesn't make any sense when used in combination with `MatChipInput`.
*/
@Directive({
selector: `input[matChipAutocomplete], textarea[matChipAutocomplete]`,
host: {
'class': 'mat-autocomplete-trigger',
'[attr.autocomplete]': 'autocompleteAttribute',
'[attr.role]': 'autocompleteDisabled ? null : "combobox"',
'[attr.aria-autocomplete]': 'autocompleteDisabled ? null : "list"',
'[attr.aria-activedescendant]': '(panelOpen && activeOption) ? activeOption.id : null',
'[attr.aria-expanded]': 'autocompleteDisabled ? null : panelOpen.toString()',
'[attr.aria-owns]': '(autocompleteDisabled || !panelOpen) ? null : autocomplete?.id',
'[attr.aria-haspopup]': '!autocompleteDisabled',
// Note: we use `focusin`, as opposed to `focus`, in order to open the panel
// a little earlier. This avoids issues where IE delays the focusing of the input.
'(focusin)': '_handleFocus()',
'(blur)': '_onTouched()',
'(input)': '_handleInput($event)',
'(keydown)': '_handleKeydown($event)',
},
exportAs: 'matAutocompleteTrigger'
})
export class MatChipAutocompleteTrigger extends MatAutocompleteTrigger {
@Input('matChipAutocomplete')
public set matChipAutocomplete(value: MatAutocomplete) {
this.autocomplete = value;
}
}
HI, I am facing the same issue, if i apply validator as "required" even when i enter fields it say formcontrol status as INVALID and value as null,
<button (click)="onSubmit()">submit
import {COMMA, ENTER} from '@angular/cdk/keycodes'; import {Component, ElementRef, ViewChild} from '@angular/core'; import {FormControl} from '@angular/forms'; import {MatAutocompleteSelectedEvent, MatChipInputEvent} from '@angular/material'; import {Observable} from 'rxjs'; import {map, startWith} from 'rxjs/operators';
/**
@title Chips Autocomplete */ @Component({ selector: 'chips-autocomplete-example', templateUrl: 'chips-autocomplete-example.html', styleUrls: ['chips-autocomplete-example.css'] }) export class ChipsAutocompleteExample { visible: boolean = true; selectable: boolean = true; removable: boolean = true; addOnBlur: boolean = false;
separatorKeysCodes = [ENTER, COMMA];
fruitCtrl = new FormControl();
filteredFruits: Observable<any[]>;
fruits = [ 'Lemon', ];
allFruits = [ 'Apple', 'Lemon', 'Lime', 'Orange', 'Strawberry' ];
@ViewChild('fruitInput') fruitInput: ElementRef;
constructor() { this.filteredFruits = this.fruitCtrl.valueChanges.pipe( startWith(null), map((fruit: string | null) => fruit ? this.filter(fruit) : this.allFruits.slice())); }
add(event: MatChipInputEvent): void { 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: any): void { const index = this.fruits.indexOf(fruit);
if (index >= 0) { this.fruits.splice(index, 1); } }
filter(name: string) { return this.allFruits.filter(fruit => fruit.toLowerCase().indexOf(name.toLowerCase()) === 0); }
selected(event: MatAutocompleteSelectedEvent): void { this.fruits.push(event.option.viewValue); this.fruitInput.nativeElement.value = ''; this.fruitCtrl.setValue(null); } }
@mlewe Thank you so much! I was facing the same issue and danced around for hours until I found your workaround, which works perfectly for me.
This issue is still present in Angular v14.
The issue is still there in angular and material 18.
Not fixed after 6 years...
Bug, feature request, or proposal:
Bug
What is the expected behavior?
Input's FormControl's setValue should work for an input that is inside a mat-form-field that has both autocomplete and chip-list.
What is the current behavior?
FormControl setValue does not work when the following iff a mat-form-field has an input that has matAutocomplete AND the mat-form-field has a mat-chip-list.
SetValue works if one removes the matAutocomplete directive from the input or removes the mat-chip-list element.
What are the steps to reproduce?
Demo should have the input incrementing a number every second, which doesn't work:
https://stackblitz.com/edit/angular-ay3yts?file=app%2Fautocomplete-simple-example.html
Deleting mat-chip-list or removing the matAutocomplete directive fixes the issue.
What is the use-case or motivation for changing an existing behavior?
I want to be able to programmatically add a chip then clear the input when an option in the autocomplete has been selected.
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
Angular: 5.2.4 Material: 5.2.4
Is there anything else we should know?
Nope :)