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.