Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mat-chip with autocomplete can add unwanted chips #13574

Open
aeslinger0 opened this issue Oct 11, 2018 · 12 comments
Open

mat-chip with autocomplete can add unwanted chips #13574

aeslinger0 opened this issue Oct 11, 2018 · 12 comments
Labels
area: material/autocomplete area: material/chips P4 A relatively minor issue that is not relevant to core functions

Comments

@aeslinger0
Copy link

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Typing a partial search term, using arrow keys to highlight option on autocomplete list, and pressing Enter should add only the selected chip.

What is the current behavior?

Intermittently, two chips are added. One for the selected value and one with the partial search term.

What are the steps to reproduce?

Providing a StackBlitz reproduction is the best way to share your issue.

StackBlitz starter: https://goo.gl/wwnhMV

I tried creating a StackBlitz to reproduce it, but couldn't get it to reproduce. Then I realized that it's a race condition causing it. More below...

What is the use-case or motivation for changing an existing behavior?

Addtional chip is unexpected behavior

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

Angular/Material >= v6 for sure.

Is there anything else we should know?

The problem happens depending on the order that event handlers get executed. The code from the official example expects the optionSelected event of the mat-autocomplete to execute first (which clears out the input box), then for the matChipInputTokenEnd event of the input to execute (which avoids adding a chip if it's blank).

For whatever reason, using the exact same code and framework version in my app, the event handlers execute in the opposite order. Since the input hasn't been cleared yet, the search term gets added as an unexpected chip. Then the option from the autocomplete gets added as the expected chip.

@dreamstride
Copy link

Seconding this issue, I have noticed the same behavior here.

I did get Stackblitz to seemingly reproduce this issue here:
https://stackblitz.com/edit/angular-yxkarc?embed=1&file=src/app/app.component.ts

Essentially what you say is the case, it will add both the currently selected value in the dropdown list as well as the partial search term you have in the autocomplete bar.

@aeslinger0
Copy link
Author

@deadlymustard, I can reproduce it using your link. What did you change to get it to happen?

@dreamstride
Copy link

I generated a project locally with the latest version of Angular CLI using the default autocomplete example on the Angular docs (https://material.angular.io/components/chips/overview) and copied and pasted it over into a fresh Stackblitz project.

@josephperrott josephperrott added the P4 A relatively minor issue that is not relevant to core functions label Nov 2, 2018
@alexfangmann
Copy link

You can fix this issue when you check the mat list for selected options.
In the selected event you have to deselect the option.
Only a workaround ^^

add(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
// Add our fruit
if ((value || '').trim()&&
// only add when no option selected
!this.matAutocomplete.options.some((x) => x.selected === true))
{
this.fruits.push(value.trim());
}
// Reset the input value
if (input) {
input.value = '';
}
this.fruitCtrl.setValue(null);
}

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

@aeslinger0
Copy link
Author

A work-around can be found here: #19279 (comment)

@robert-king
Copy link

robert-king commented Jul 18, 2022

for what it's worth, I got this error today even after updating all my dependencies...

"@angular/animations": "~14.0.6",
"@angular/cdk": "^14.0.5",
"@angular/common": "~14.0.6",
"@angular/compiler": "~14.0.6",
"@angular/core": "~14.0.6",
"@angular/forms": "~14.0.6",
"@angular/material": "^14.0.5",
"@angular/platform-browser": "~14.0.6",
"@angular/platform-browser-dynamic": "~14.0.6",
"@angular/router": "~14.0.6",

to fix it I just had to swap the order of the two imports to make sure selected(event: MatAutocompleteSelectedEvent) is called before remove(fruit: string):



  imports: [
SharedModule,
MatChipsModule,
MatAutocompleteModule,

],

imports: [
SharedModule,
MatAutocompleteModule,
MatChipsModule,

],

I tried to reproduce this by editing the example code and swapping the import order (https://stackblitz.com/run?file=src/app/chips-autocomplete-example.ts), however, I wasn't able to reproduce it. There are three potential reasons i could think of as to why it wouldn't reproduce, but I decided to leave it there. Potentially it's because stackblitz wasn't respecting the change of module import order, potentially it's because in the stackblitz example, the component example is the component that is bootstrapped and that affects how the modules are imported?, few other reasons. good luck.

@Porkite
Copy link

Porkite commented Sep 15, 2022

This problem is related to the order of the imports in module
@deadlymustard
when you change list of imports:

BrowserModule,
BrowserAnimationsModule,
MatFormFieldModule,
MatInputModule,
MatChipsModule,
MatIconModule,
FormsModule,
ReactiveFormsModule,
MatAutocompleteModule

to

BrowserModule,
BrowserAnimationsModule,
MatAutocompleteModule,
MatChipsModule,
MatFormFieldModule,
MatInputModule,
MatIconModule,
FormsModule,
ReactiveFormsModule

works like a charm,

example:
https://stackblitz.com/edit/angular-fejzma?file=src%2Fapp%2Fapp.module.ts,src%2Fmaterial.module.ts

However, importing order should not cause such errors

@onedapperterm
Copy link

onedapperterm commented Sep 29, 2022

Oh Man! Thank ya! that behavior is just so weird. I lost almost an hour trying to find the solution and I never thought that was the order on the inputs! now it works smoothly! :D

@bahaabeih
Copy link

bahaabeih commented Nov 25, 2022

I spent a day on and off trying to find a reasonable explanation. When I gave up I started searching for nonsensical reasons, and stumbled on the solution here. I wouldn't have expected this to be allowed to happen in angular! The order of the handlers should be deterministic or at least manual!

To add a bit more clarity, the order of modules MatAutoCompleteModule and MatChipsModule is what decides, whether this bug occurs or not.

@mpflanzer
Copy link

mpflanzer commented Sep 11, 2023

I think it would be worth fixing the order of imports in the official example: https://material.angular.io/components/chips/overview#chips-autocomplete At least then not everyone using it as a starting point is stuck with this problem.

As I just started with Angular I've no idea what's possible or not. But I think it would be nice to emit a warning (console or terminal) if the order is wrong. That would save developers quite some time to debug this behavior.

@its-dibo
Copy link

!this.matAutocomplete.options.some((x) => x.selected === true)) {

from where you get this.matAutocomplete?

@rubenheymans
Copy link

Why is there no full example where you can never add items that are not in the allFruits array, and use objects instead of strings. Real world examples would be so much better

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: material/autocomplete area: material/chips P4 A relatively minor issue that is not relevant to core functions
Projects
None yet
Development

No branches or pull requests