Angular2 selected option with objects
Asked Answered
G

3

6

I have an Angular 2 app that is dealing with customers and a spring rest back end. The customer object has a customer type, which is also an object, and I have the drop down on the customer form working so that objects are stored as the value, however I can't figure out how to select the correct customer type when an existing customer is loaded into the form.

<select  class="form-control" required [(ngModel)]="customer.customerType" >
   <option *ngFor="let ct of customerTypes" [ngValue]="ct">{{ct.customerType}}</option>
</select>

In the above snippet if the customer already has a customer type, then the dropdown won't select any value. I remember having the same problem with angular1 which was solved using ngOptions:

<select ng-model="customer.customerType"
        ng-options="customerType.customerType for customerType in customerTypes 
        track by customerType.customerType" >
</select>

So, my question is, how to replicate the way Angular1 solved this problem in Angular 2

Grounder answered 9/6, 2016 at 20:16 Comment(3)
Just assigning the default value to customer.customerType should do what you want. ngValue and customer.customerType need to point to the same object instance, not only to two objects with the same content.Issi
I'd realised that it needed the same object instance, rather than objects with the same content, but I was wondering if there was a way that the select could be passed a something similar to a comparitor in java parlance, that it would use to evaluate whether the object instances are the same. I've ended up swapping out the the instance that is returned in the rest call, with the equivalent object from the select options, which feels really clunky.Grounder
Possible duplicate of Binding select element to object in Angular 2Weighbridge
G
0

I've taken the slightly clunky approach of replacing the instance of CustomerType that is returned in my Customer object, with that held in the CustomerType array. This can only be done once both the Customer and CustomerTypes have been returned from the backed:

ngOnInit() {
    let id = this._routeParams.get('id');
    this._service.getCustomer(id).subscribe(customer => {
      this.customer = customer;
      this.updateCustomerType();
    });
    this._service.getCustomerTypes().subscribe(customerTypes =>{
      this.customerTypes = customerTypes;
      this.updateCustomerType();
    });
}
private updateCustomerType(): void{
  if(this.customer.customerType != null && this.customerTypes.length != null){
    for (var customerType of this.customerTypes) {
      console.log("Customer Type: ", customerType);
      if(this.customer.customerType.id == customerType.id){
        this.customer.customerType = customerType;
      }
    }
  }
}
Grounder answered 13/6, 2016 at 20:5 Comment(0)
E
7

I had the same Problem and i solved it this way:

<select  class="form-control" required [(ngModel)]="customer.customerType" >
   <option *ngFor="let ct of customerTypes" 
        [ngValue]="ct"   
        [attr.selected]="customer.customerType.customerType==ct.customerType ? true : null"
       >{{ct.customerType}}</option>
</select> 

Thanks to Günter Zöchbauer

Eimile answered 22/8, 2016 at 9:9 Comment(0)
E
0

I suggest you change the approach for building this, by creating a select component:

import {Component, Output, EventEmitter} from 'angular2/core';

@Component({
    selector: 'custype-selector',
    template: `
    <div>
        <label>Cust type</label>
        <select #sel (change)="select.emit(sel.value)">
            <option *ngFor="#custype of customertypes"> {{custype}} </option>
        </select>
    </div>`
})
export class CusTypeSelector {
    @Output() select = new EventEmitter();
    customertypes= ["type1", "type2"]

    ngOnInit(){
        this.select.emit(this.customertypes[0]);
    } 
}

I've hardcoded the array into selector, but you can of course add an Input parameter to the component with your customertypes if you like

you could then use the above component like this:

<custype-selector (select)="custype = $event"></custype-selector>
Eisenberg answered 9/6, 2016 at 21:33 Comment(1)
Thanks, I like the look of this, and will give it a go. Out of interest, is there a reason you said that the customer types could be provided as a parameter, rather it including the service that fetches the customer types from the backend REST api? I could see it being useful that a drop down list component is able to fetch it's list of options itself.Grounder
G
0

I've taken the slightly clunky approach of replacing the instance of CustomerType that is returned in my Customer object, with that held in the CustomerType array. This can only be done once both the Customer and CustomerTypes have been returned from the backed:

ngOnInit() {
    let id = this._routeParams.get('id');
    this._service.getCustomer(id).subscribe(customer => {
      this.customer = customer;
      this.updateCustomerType();
    });
    this._service.getCustomerTypes().subscribe(customerTypes =>{
      this.customerTypes = customerTypes;
      this.updateCustomerType();
    });
}
private updateCustomerType(): void{
  if(this.customer.customerType != null && this.customerTypes.length != null){
    for (var customerType of this.customerTypes) {
      console.log("Customer Type: ", customerType);
      if(this.customer.customerType.id == customerType.id){
        this.customer.customerType = customerType;
      }
    }
  }
}
Grounder answered 13/6, 2016 at 20:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.