Comment puis-je obtenir une nouvelle sélection dans «sélectionner» dans Angular 2?

372

J'utilise Angular 2 (TypeScript).

Je veux faire quelque chose avec la nouvelle sélection, mais je reçois onChange()toujours la dernière sélection. Comment puis-je obtenir la nouvelle sélection?

<select [(ngModel)]="selectedDevice" (change)="onChange($event)">
   <option *ngFor="#i of devices">{{i}}</option>
</select>
onChange($event) {
    console.log(this.selectedDevice);
    // I want to do something here with the new selectedDevice, but what I
    // get here is always the last selection, not the one I just selected.
}
Hongbo Miao
la source

Réponses:

751

Si vous n'avez pas besoin d'une liaison de données bidirectionnelle:

<select (change)="onChange($event.target.value)">
    <option *ngFor="let i of devices">{{i}}</option>
</select>

onChange(deviceValue) {
    console.log(deviceValue);
}

Pour la liaison de données bidirectionnelle, séparez les liaisons d'événement et de propriété:

<select [ngModel]="selectedDevice" (ngModelChange)="onChange($event)" name="sel2">
    <option [value]="i" *ngFor="let i of devices">{{i}}</option>
</select>
export class AppComponent {
  devices = 'one two three'.split(' ');
  selectedDevice = 'two';
  onChange(newValue) {
    console.log(newValue);
    this.selectedDevice = newValue;
    // ... do other stuff here ...
}

Si devicesest un tableau d'objets, liez à ngValueau lieu de value:

<select [ngModel]="selectedDeviceObj" (ngModelChange)="onChangeObj($event)" name="sel3">
  <option [ngValue]="i" *ngFor="let i of deviceObjects">{{i.name}}</option>
</select>
{{selectedDeviceObj | json}}
export class AppComponent {
  deviceObjects = [{name: 1}, {name: 2}, {name: 3}];
  selectedDeviceObj = this.deviceObjects[1];
  onChangeObj(newObj) {
    console.log(newObj);
    this.selectedDeviceObj = newObj;
    // ... do other stuff here ...
  }
}

Plunker- n'utilise pas <form>
Plunker- utilise <form>et utilise la nouvelle API de formulaires

Mark Rajcok
la source
anwere a raison mais quel est le rôle de ngModel ici m encore confus allez-vous l'expliquer?
Pardeep Jain
1
@PardeepJain, l'utilisation de la liaison de données bidirectionnelle avec NgModel entraîne Angular à 1) automatiquement la mise selectedDeviceà jour lorsque l'utilisateur sélectionne un élément différent, et 2) si nous définissons la valeur de selectedDevice, NgModel mettra automatiquement à jour la vue. Comme nous voulons également être informés d'un changement, j'ai ajouté la (change)liaison d'événement. Nous ne devrions pas avoir à le faire de cette façon ... nous devrions être en mesure de diviser la liaison de données bidirectionnelle en [ngModel]="selectedDevice" and (ngModelChange)="onChange($event)", mais comme je l'ai découvert, onChange()est appelé deux fois pour chaque changement de liste de sélection de cette façon.
Mark Rajcok
ok merci encore une chose s'il vous plait. je veux obtenir la valeur de: <option *ngFor="#course of course_array #i=index" #newone value={{course.id}} >{{course.course_name}}</option> course.course_nameet les course.iddeux comment puis-je envoyer ces deux via la fonction (changer)?
Pardeep Jain
1
@HongboMiao, la $eventvariable / le symbole spécial fait partie du "contexte d'instruction" des instructions de modèle angulaire. Si à la place j'écrivais (ngModelChange)="onChange('abc')"alors newValuej'obtiendrais la chaîne abc. C'est juste un appel normal à une fonction JavaScript.
Mark Rajcok
2
@HongboMiao, utilisez [ngValue] si vous avez un tableau d'objets. Utilisez [valeur] si vous avez un tableau de types primitifs (chaîne, booléen, entier).
Mark Rajcok
40

Vous pouvez retransmettre la valeur dans le composant en créant une variable de référence sur la balise select #deviceet en la passant dans le gestionnaire de modifications onChange($event, device.value)devrait avoir la nouvelle valeur

<select [(ng-model)]="selectedDevice" #device (change)="onChange($event, device.value)">
    <option *ng-for="#i of devices">{{i}}</option>
</select>

onChange($event, deviceValue) {
    console.log(deviceValue);
}
Brocco
la source
1
Vous n'êtes pas lié ngModelici, vous êtes lié à une nouvelle variable appelée device.
lux
4
quel est le rôle d' [(ngModel)]ici
Pardeep Jain
2
@Brocco Le vôtre et celui de Mark sont corrects. J'espère que vous pouvez comprendre que je ne peux choisir qu'une seule réponse. :)
Hongbo Miao
22

Utilisez simplement [ngValue] au lieu de [value] !!

export class Organisation {
  description: string;
  id: string;
  name: string;
}
export class ScheduleComponent implements OnInit {
  selectedOrg: Organisation;
  orgs: Organisation[] = [];

  constructor(private organisationService: OrganisationService) {}

  get selectedOrgMod() {
    return this.selectedOrg;
  }

  set selectedOrgMod(value) {
    this.selectedOrg = value;
  }
}


<div class="form-group">
      <label for="organisation">Organisation
      <select id="organisation" class="form-control" [(ngModel)]="selectedOrgMod" required>
        <option *ngFor="let org of orgs" [ngValue]="org">{{org.name}}</option>
      </select>
      </label>
</div>
Robert King
la source
1
Cela m'a aidé. Je ne sais pas si mon cas est légèrement différent, mais pour moi, (change)="selectOrg(selectedOrg)"appelle la fonction selectOrg avec la sélection actuelle / précédente, pas l'option nouvellement sélectionnée. J'ai compris, je n'ai même pas besoin du (change)bit.
Nick
Bon repérage. oui c'est un comportement étrange avec (changement) en passant l'ancien modèle. Je pensais que ce serait comme ng-change, c'est peut-être un bug dans angular2. Je l'ai mis à jour pour utiliser les méthodes get et set. De cette façon, dans la méthode set selectedOrgMod (valeur), je peux savoir que l'organisation a changé et mettre à jour ma liste d'équipes organisationnelles.
robert king
12

J'ai rencontré ce problème lors du didacticiel sur les formulaires Angular 2 (version TypeScript) sur https://angular.io/docs/ts/latest/guide/forms.html

Le bloc de sélection / option ne permettait pas de modifier la valeur de la sélection en sélectionnant l'une des options.

Faire ce que Mark Rajcok a suggéré a fonctionné, bien que je me demande s'il y a quelque chose que j'ai manqué dans le tutoriel d'origine ou s'il y a eu une mise à jour. Dans tous les cas, l'ajout

onChange(newVal) {
    this.model.power = newVal;
}

à hero-form.component.ts dans la classe HeroFormComponent

et

(change)="onChange($event.target.value)"

à hero-form.component.html dans l' <select>élément l'a fait fonctionner

jarisky
la source
4

utilisez selectionChange en angulaire 6 et plus. exemple (selectionChange)= onChange($event.value)

Valentin
la source
Je n'ai pas utilisé l'approche de forme réactive. J'ai juste besoin d'une valeur sélectionnée pour déclencher un appel de service basé sur cette valeur unique .. la méthode ci-dessus m'a aidé.
anavaras lamurep
3

Une autre option consiste à stocker l'objet en valeur sous forme de chaîne:

<select [ngModel]="selectedDevice | json" (ngModelChange)="onChange($event)">
    <option [value]="i | json" *ngFor="let i of devices">{{i}}</option>
</select>

composant:

onChange(val) {
    this.selectedDevice = JSON.parse(val);
}

C'était la seule façon de faire fonctionner la liaison bidirectionnelle pour définir la valeur de sélection au chargement de la page. En effet, ma liste qui remplit la zone de sélection n'était pas exactement le même objet auquel ma sélection était liée et elle doit être le même objet, pas seulement les mêmes valeurs de propriété.

kravits88
la source
3
<mat-form-field>
<mat-select placeholder="Vacancies" [(ngModel)]="vacanciesSpinnerSelectedItem.code" (ngModelChange)="spinnerClick1($event)"
    [ngModelOptions]="{standalone: true}" required>
    <mat-option *ngFor="let spinnerValue of vacanciesSpinnerValues" [value]="spinnerValue?.code">{{spinnerValue.description}}</mat-option>
</mat-select>

Je l'ai utilisé pour la liste déroulante angulaire du matériau. fonctionne bien

Apurv
la source
1

la dernière version ionique 3.2.0 a changé (changer) en (ionChange)

par exemple: HTML

<ion-select (ionChange)="function($event)"> <ion-option>1<ion-option>
</ion-select>

TS

function($event){
// this gives the selected element
 console.log($event);

}
déraper
la source
1

Angulaire 7/8

Depuis angular 6, l'utilisation de la propriété d'entrée ngModel avec la directive sur les formes réactives est obsolète et supprimée dans Angular 7+. Lisez le document officiel ici.

En utilisant l'approche par formulaire réactif, vous pouvez obtenir / définir les données sélectionnées comme;

      //in your template
 <select formControlName="person" (change)="onChange($event)"class="form-control">
    <option [value]="null" disabled>Choose person</option>
      <option *ngFor="let person of persons" [value]="person"> 
        {{person.name}}
    </option>
 </select> 


 //in your ts
 onChange($event) {
    let person = this.peopleForm.get("person").value
    console.log("selected person--->", person);
    // this.peopleForm.get("person").setValue(person.id);
  }
7guyo
la source
0

Dans Angular 5, je l'ai fait de la manière suivante. récupère l'objet $ event.value au lieu de $ event.target.value

<mat-form-field color="warn">
   <mat-select (ngModelChange)="onChangeTown($event)" class="form-width" formControlName="branch" [(ngModel)]="branch" placeholder="Enter branch">
     <mat-option *ngFor="let branch of branchs" [value]="branch.value">
                  {{ branch.name }}
     </mat-option>
   </mat-select>
</mat-form-field>

onChangeTown(event): void {
  const selectedTown = event;
  console.log('selectedTown: ', selectedTown);
}
Kumaresan Perumal
la source
0

Dans Angular 8, vous pouvez simplement utiliser "selectionChange" comme ceci:

 <mat-select  [(value)]="selectedData" (selectionChange)="onChange()" >
  <mat-option *ngFor="let i of data" [value]="i.ItemID">
  {{i.ItemName}}
  </mat-option>
 </mat-select>
B.Habibzadeh
la source