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

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


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

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>

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ł


4

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


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.


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


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

}

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

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

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>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.