Jak mogę uzyskać nowy wybór w „select” w Angular 2?

372

Używam Angular 2 (TypeScript).

Chcę coś zrobić z nową selekcją, ale onChange()zawsze dostaję ostatnią selekcję. Jak mogę uzyskać nowy wybór?

<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
źródło

Odpowiedzi:

749

Jeśli nie potrzebujesz dwukierunkowego wiązania danych:

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

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

W przypadku dwukierunkowego powiązania danych oddziel powiązanie zdarzenia i właściwości:

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

Jeśli devicesjest tablicą obiektów, powiąż z ngValuezamiast 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- nie używa <form>
Plunker- używa <form>i używa nowego interfejsu API formularzy

Mark Rajcok
źródło
anwere ma rację, ale jaka jest tu rola ngModela, nadal jestem zdezorientowany, czy to wyjaśnisz?
Pardeep Jain
1
@PardeepJain, użycie dwukierunkowego powiązania danych z NgModel powoduje, że Angular do 1) automatycznie aktualizuje się, selectedDevicegdy użytkownik wybierze inny element, i 2) jeśli ustawimy wartość selectedDevice, NgModel automatycznie zaktualizuje widok. Ponieważ chcemy również otrzymywać powiadomienia o zmianie, dodałem (change)powiązanie zdarzenia. Nie powinniśmy tego robić w ten sposób ... powinniśmy być w stanie rozbić dwukierunkowe wiązanie danych [ngModel]="selectedDevice" and (ngModelChange)="onChange($event)", ale jak się dowiedziałem, onChange()jest wywoływany dwukrotnie za każdą zmianę listy wyboru w ten sposób.
Mark Rajcok
dobrze, dziękuję jeszcze jedno. chcę uzyskać wartość: <option *ngFor="#course of course_array #i=index" #newone value={{course.id}} >{{course.course_name}}</option> course.course_namei course.idoba, w jaki sposób mogę wysłać te dwa za pomocą (zmiany) funkcji?
Pardeep Jain
1
@HongboMiao, specjalna $eventzmienna / symbol jest częścią „kontekstu instrukcji”, który posiadają instrukcje szablonu Angular. Jeśli zamiast Pisałem (ngModelChange)="onChange('abc')"wtedy newValuedostanie ciąg abc. To tylko normalne wywołanie funkcji JavaScript.
Mark Rajcok,
2
@HongboMiao, użyj [ngValue], jeśli masz tablicę obiektów. Użyj [wartość], jeśli masz tablicę typów pierwotnych (łańcuch, wartość logiczna, liczba całkowita).
Mark Rajcok
40

Możesz przekazać wartość z powrotem do komponentu, tworząc zmienną referencyjną w znaczniku select #devicei przekazując ją do modułu obsługi zmian onChange($event, device.value)powinien mieć nową wartość

<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
źródło
1
Nie wiążesz się ngModeltutaj, wiążesz się z nową zmienną o nazwie device.
luks
4
o co [(ngModel)]tu chodzi
Pardeep Jain
2
@Brocco Zarówno twoje, jak i Marka mają rację. Mam nadzieję, że rozumiesz, że mogę wybrać tylko jedną odpowiedź. :)
Hongbo Miao,
22

Wystarczy użyć [ngValue] zamiast [wartość] !!

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
źródło
1
To mi pomogło. Nie jestem pewien, czy moja sprawa jest nieco inna, ale dla mnie (change)="selectOrg(selectedOrg)"wywołuje funkcję selectOrg z bieżącym / poprzednim wyborem, a nie nowo wybraną opcją. Zrozumiałem, że nawet nie potrzebuję (change)trochę.
Nick
Dobre plamienie. tak, to dziwne zachowanie przy (zmianie) przechodzącej przez stary model. Pomyślałem, że to może być zmiana ng, może to błąd w angular2. Zaktualizowałem go, aby używać metod pobierania i ustawiania. W ten sposób w ustawionej metodzie selectedOrgMod (wartość) mogę wiedzieć, że organizacja zmieniła się i zaktualizować moją listę zespołów organizacyjnych.
Robert King
12

Napotkałem ten problem podczas samouczka formularzy Angular 2 (wersja TypeScript) pod adresem https://angular.io/docs/ts/latest/guide/forms.html

Blok wyboru / opcji nie pozwalał na zmianę wartości zaznaczenia poprzez wybranie jednej z opcji.

Robienie tego, co zasugerował Mark Rajcok, zadziałało, chociaż zastanawiam się, czy coś mi umknęło w oryginalnym samouczku, czy też była aktualizacja. W każdym razie dodawanie

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

do hero-form.component.ts w klasie HeroFormComponent

i

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

do hero-form.component.html w <select>elemencie sprawiło, że działał

jarisky
źródło
4

użyj wyboru Zmień w kącie 6 i wyższym. przykład (selectionChange)= onChange($event.value)

cicha sympatia
źródło
Nie użyłem podejścia reaktywnego. Potrzebuję tylko wybranej wartości, aby wywołać zgłoszenie serwisowe w oparciu o tę pojedynczą wartość. Powyższa metoda pomogła mi.
anavaras lamurep
3

Inną opcją jest przechowywanie obiektu w wartości jako ciągu:

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

składnik:

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

To był jedyny sposób, w jaki mogłem uzyskać dwukierunkowe wiązanie działające, aby ustawić wybraną wartość przy ładowaniu strony. Stało się tak, ponieważ moja lista wypełniająca pole wyboru nie była dokładnie tym samym obiektem, z którym była związana moja selekcja i musi być tym samym obiektem, a nie tylko tymi samymi wartościami właściwości.

kravits88
źródło
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>

Użyłem tego do rozwijania materiału kątowego. działa w porządku

Apurv
źródło
1

najnowszy ionic 3.2.0 zmodyfikował (zmień) na (ionChange)

np .: HTML

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

TS

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

}
poślizg
źródło
1

Kątowy 7/8

Począwszy od kąta 6, użycie właściwości wejściowej ngModel z dyrektywą form reaktywnych zostało przestarzałe i całkowicie usunięte w kanciastym 7+. Przeczytaj oficjalny dokument tutaj.

Stosując podejście reaktywne, możesz pobrać / ustawić wybrane dane jako;

      //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
źródło
0

W Angular 5 zrobiłem w następujący sposób. pobierz obiekt $ event.value zamiast $ 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
źródło
0

W Angular 8 możesz po prostu użyć „selectionChange” w następujący sposób:

 <mat-select  [(value)]="selectedData" (selectionChange)="onChange()" >
  <mat-option *ngFor="let i of data" [value]="i.ItemID">
  {{i.ItemName}}
  </mat-option>
 </mat-select>
B.Hibibzadeh
źródło