Come posso ottenere una nuova selezione in "select" in Angular 2?


372

Sto usando Angular 2 (TypeScript).

Voglio fare qualcosa con la nuova selezione, ma quello che ottengo onChange()è sempre l'ultima selezione. Come posso ottenere la nuova selezione?

<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.
}

Risposte:


751

Se non hai bisogno di un'associazione dati bidirezionale:

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

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

Per l'associazione dati bidirezionale, separare i collegamenti evento e proprietà:

<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 ...
}

Se devicesè una matrice di oggetti, associa ngValueinvece di 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- non utilizza <form>
Plunker: utilizza <form>e utilizza l'API dei nuovi moduli


Qualcuno ha ragione, ma qual è il ruolo di ngModel, qui sono ancora confuso.
Pardeep Jain,

1
@PardeepJain, l'uso dell'associazione dati bidirezionale con NgModel fa sì che Angular sia 1) si aggiorni automaticamente selectedDevicequando l'utente seleziona un altro elemento e 2) se impostiamo il valore di selectedDevice, NgModel aggiornerà automaticamente la vista. Dato che vogliamo anche essere informati di una modifica, ho aggiunto il (change)binding dell'evento. Non dovremmo farlo in questo modo ... dovremmo essere in grado di rompere l'associazione dei dati a due vie [ngModel]="selectedDevice" and (ngModelChange)="onChange($event)", ma come ho scoperto, onChange()viene chiamato due volte per ogni elenco di selezione che cambia in quel modo.
Mark Rajcok,

ok grazie ancora una cosa per favore. voglio ottenere il valore di: <option *ngFor="#course of course_array #i=index" #newone value={{course.id}} >{{course.course_name}}</option> course.course_nameed course.identrambi come posso inviare questi due tramite la funzione (modifica)?
Pardeep Jain,

1
@HongboMiao, la speciale $eventvariabile / simbolo fa parte del "contesto delle istruzioni" che hanno le dichiarazioni dei modelli angolari. Se invece scrivessi, (ngModelChange)="onChange('abc')"allora newValueotterrei la stringa abc. È solo una normale chiamata della funzione JavaScript.
Mark Rajcok,

2
@HongboMiao, usa [ngValue] se hai una matrice di oggetti. Utilizzare [valore] se si dispone di una matrice di tipi primitivi (stringa, booleano, intero).
Mark Rajcok,

40

È possibile restituire il valore al componente creando una variabile di riferimento sul tag select #devicee passandolo nel gestore modifiche onChange($event, device.value)dovrebbe avere il nuovo valore

<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);
}

1
Non stai vincolando ngModelqui, stai vincolando a una nuova variabile chiamata device.
lux

4
Qual è il rotolo di [(ngModel)]qui
Pardeep Jain,

2
@Brocco Sia il tuo che quello di Mark sono corretti. Spero che tu possa capire, posso solo scegliere una risposta. :)
Hongbo Miao,

22

Basta usare [ngValue] invece di [valore] !!

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>

1
Questo mi ha aiutato. Non sono sicuro che il mio caso sia leggermente diverso, ma per me (change)="selectOrg(selectedOrg)"chiama la funzione selectOrg con la selezione corrente / precedente, non l'opzione appena selezionata. Ho capito, non mi serve nemmeno un (change)po '.
Nick,

Buon avvistamento. sì, è un comportamento strano con (modifica) il passaggio del vecchio modello. Ho pensato che sarebbe stato come ng-change forse è un bug in angular2. L'ho aggiornato per utilizzare i metodi get e set. In questo modo nel set setOrgMod (value) metodo posso sapere che l'organizzazione è cambiata e aggiornare il mio elenco di team organizzativi.
robert king,

12

Ho riscontrato questo problema durante l'esercitazione su Angular 2 form (versione TypeScript) su https://angular.io/docs/ts/latest/guide/forms.html

Il blocco select / option non consentiva di modificare il valore della selezione selezionando una delle opzioni.

Fare ciò che Mark Rajcok ha suggerito ha funzionato, anche se mi chiedo se c'è qualcosa che mi è sfuggito nel tutorial originale o se c'è stato un aggiornamento. In ogni caso, aggiungendo

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

a hero-form.component.ts nella classe HeroFormComponent

e

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

a hero-form.component.html nell'elemento l'ha <select>fatto funzionare


4

usa selectionCambia in angolare 6 e sopra. esempio (selectionChange)= onChange($event.value)


Non ho usato un approccio in forma reattiva. Ho solo bisogno di un valore selezionato per innescare una chiamata di servizio basata su quel singolo valore .. il metodo sopra mi ha aiutato.
anavaras lamurep,

3

Un'altra opzione è quella di memorizzare l'oggetto nel valore come una stringa:

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

componente:

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

Questo è stato l'unico modo in cui ho potuto far funzionare l'associazione bidirezionale per impostare il valore di selezione al caricamento della pagina. Questo perché il mio elenco che popola la casella di selezione non era esattamente lo stesso oggetto a cui era associata la mia selezione e deve essere lo stesso oggetto, non solo gli stessi valori di proprietà.


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>

L'ho usato per il menu a discesa del materiale angolare. funziona bene


1

l'ultimo ionico 3.2.0 è stato modificato (cambia) in (ionChange)

ad es .: HTML

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

TS

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

}

1

Angolare 7/8

A partire dall'angolare 6, l'uso della proprietà di input ngModel con la direttiva sulle forme reattive è stato deprecato e rimosso del tutto in angolare 7+. Leggi il documento ufficiale qui.

Utilizzando l'approccio a forma reattiva è possibile ottenere / impostare i dati selezionati come;

      //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);
  }

0

In Angular 5 l' ho fatto nel modo seguente. ottenere l'oggetto $ event.value invece di $ 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);
}

0

In Angular 8 puoi semplicemente usare "selectionChange" in questo modo:

 <mat-select  [(value)]="selectedData" (selectionChange)="onChange()" >
  <mat-option *ngFor="let i of data" [value]="i.ItemID">
  {{i.ItemName}}
  </mat-option>
 </mat-select>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.