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

MdAutocomplete onSelectionChange fired multiple times #7369

Closed
Vadorequest opened this issue Sep 27, 2017 · 11 comments
Closed

MdAutocomplete onSelectionChange fired multiple times #7369

Vadorequest opened this issue Sep 27, 2017 · 11 comments

Comments

@Vadorequest
Copy link

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Fire only once with the correct value.

What is the current behavior?

The event onSelectionChange fires twice instead of once. The first time with the correct value, the second time with the last used value.

Also, the behavior changes if we select the value through the keyboard (arrow keys), in this case it fires twice onSelectionChange and once onKeyupEnter.
Since pressing the enter key automatically fires the onSelectionChange event, I removed it. (but this should probably be fixed somehow to behave properly, or not, depends on you)

image

But, even if I disable the onKeyupEnter, I keep getting two events fired instead of one and didn't find a fix around that.

    <form>
      <i class="material-icons">search</i>
      <md-form-field>
        <input
          type="text"
          mdInput
          placeholder="Search"
          [formControl]="textFilterControl"
          [mdAutocomplete]="auto"
          (keyup.enter)="onKeyupEnter($event)" // I eventually removed that, duplicated event fired (3rd)
        >
      </md-form-field>
      <md-autocomplete #auto="mdAutocomplete">
         <md-option
           *ngFor="let movie of filteredMovies | async"
           [value]="movie.title"
           (onSelectionChange)="onSelectionChange($event)" // Fires two events instead of one.
         >
            {{ movie.title }}
         </md-option>
      </md-autocomplete>
    </form>

What are the steps to reproduce?

Try selecting several times a value in the list. Works correctly only the first time.

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

"dependencies": {
    "@angular-redux/store": "6.5.7",
    "@angular/animations": "4.4.3",
    "@angular/cdk": "2.0.0-beta.11",
    "@angular/common": "^4.2.4",
    "@angular/compiler": "^4.2.4",
    "@angular/core": "^4.2.4",
    "@angular/forms": "^4.2.4",
    "@angular/http": "^4.2.4",
    "@angular/material": "2.0.0-beta.11",
    "@angular/platform-browser": "^4.2.4",
    "@angular/platform-browser-dynamic": "^4.2.4",
    "@angular/router": "^4.2.4",
    "core-js": "^2.4.1",
    "hammerjs": "2.0.8",
    "redux": "3.7.2",
    "redux-logger": "3.0.6",
    "rxjs": "^5.4.2",
    "zone.js": "^0.8.14"
  },
  "devDependencies": {
    "@angular/cli": "1.4.3",
    "@angular/compiler-cli": "^4.2.4",
    "@angular/language-service": "^4.2.4",
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "6.0.88",
    "@types/redux-logger": "3.0.4",
    "codelyzer": "~3.1.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.2.0",
    "tslint": "~5.3.2",
    "typescript": "~2.3.3"
  }

Is there anything else we should know?

Seems related to #4356

You can reproduce the issue through this repository: https://github.com/Vadorequest/challenge-awesome-movies-viewer/blob/master/src/app/header/header.component.html

A simple clone & npm install should do. App runs on http://localhost:4200/

@willshowell
Copy link
Contributor

willshowell commented Sep 27, 2017

This is expected behavior. The first event, selected: true, is coming from the option you clicked on. The second event is coming from a different option, the one that is now deselected. As in, it's selection state has changed.

The order of the events could arguably be reversed, but I really doubt it's a big deal since most use cases are likely filtering on one or the other by selected or isUserInput.

MatAutocomplete has an optionSelected output specifically for this. It emits once whenever an option is selected. Based on your example repo, that should be suitable for your use case.

(also see #4094 (comment))

@crisbeto
Copy link
Member

Thanks for the comment @willshowell, that is correct. Closing since it works as expected.

@Vadorequest
Copy link
Author

Indeed, thanks!

@RichardBoyder
Copy link

RichardBoyder commented Oct 26, 2017

Hi Guys, So im a bit lost. what is the solution for this ? To detect a change on Ngfor ?

eg. <mat-option *ngFor="let beneficiary of beneficiaryList" [value]="beneficiary.value">

how would i get the selected option and pass through the beneficiary.value to a function?

how does MatAutocomplete has an optionSelected work? will it do what i need it to as above?

@Vadorequest
Copy link
Author

@RichardBoyder this is how I fixed it: Vadorequest/challenge-awesome-movies-viewer@8e1db4e

@RichardBoyder
Copy link

Cool thankyou for that. Awesome

@willshowell
Copy link
Contributor

@RichardBoyder also yes, the optionSelected event will work for your use case. It was added to specifically address this problem.

<mat-autocomplete (optionSelected)="selectBeneficiary($event.option.value)">
  <mat-option *ngFor="let beneficiary of beneficiaryList" [value]="beneficiary.value">
</mat-autocomplete>
selectBeneficiary(value) {
  const selected = this.beneficiaryList.find(b => b.value === value);
  console.log('You selected beneficiary:', selected);
}

@kevincaradant
Copy link

kevincaradant commented Nov 4, 2017

Hi

It's seems you want only get the value (string) of <md-option>. In my case, I want get the full object "user".

Someone have an idea to do that without the "onSelectionChange" event which fire twice ( new / old value )

This is my snippet code :)

<md-autocomplete (optionSelected)="onSelectedUser.emit($event)" #reactiveAuto="mdAutocomplete">
  <md-option *ngFor="let user of users$ | async">
    <span>{{user.login}}  - {{user.firstName}} {{user.lastName}} ({{user.company}})</span>
  </md-option>
</md-autocomplete>

thank you

PS: With $event.option.viewValue, I can get the value (string) of the option so the login, lastname etc but I don't undestand how to get the object USER ;)

Edit: Ok I got it. I have to use the [displayWith] input in <mat-autocomplete> and the [value] input in the <mat-option> Problem SOLVED :)

@THUONGBUIANH
Copy link

@willshowell
It helps me

@ctp-placebo
Copy link

@willshowell 's solution worked for us. There is a problem here that the documentation currently references this in the API but nowhere in the Overview page, and not in any of the example provided either. I would have thought the examples would use the API... Very hard to find good information on this. /moan

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants