1

I currently have a drop down box on my HTML page that the users selects from. Once they select a choice like "Jeep" it will pass that to my component to then use this value. I am curious if it is possible to send back two separate variables at the same time. I would like to pass back their selection of "Jeep" as well as another value from the same JSON data set such as "Black".

Below is the code I use to get the "Jeep" into my component. Note the data is like this cars.

{name: "Jeep", color: "Black"}

cars.component.html

 <p>Select Car</p>
 <select class="form-control" (change)="changedCar($event)" >
       <option value="">Select Car</option>
       <option *ngFor="let car of cars" value="{{car.name}}">{{car.name}}/option>
</select>

cars.component.ts

 changedCar (event: any) {
      this.selectedName = event.target.value;
      console.log(this.selectedName );
 }

So currently I have this console.log producing "Jeep" as desired. Is it possible to send something so that I can have this.selectedColor and it produce "Black"?

I am very new so I apologize if this is a bad question.

EDIT: Sorry for not adding enough detail at first. -- I wanted to keep it as simple as possible for a easy fix. I will now include all the details.

cars.component.ts more

ngOnInit() {
  this.databaseService.getCar().subscribe(
    cars => this.cars = cars
  );

database.service.ts

export class Car {
  car: string;
}

getCar(): Observable<Car[]> {
  const url = 'http://localhost:3000/car';
  const data = ({
  });
  return this._http.post(url, data)
  .pipe(
    map((res) => {
      console.log(res);
      return <Car[]> res;
    })
  );
}
user68288
  • 702
  • 2
  • 6
  • 27

5 Answers5

1

Try the following code cars is an array this array is going to content multiple objects like this:

component.ts

cars =[ {
      id: 1,
      brand: 'Jeep',
      color: 'black'
    },
    {
      id: 2,
      brand: 'Honda',
      color: 'blue'
    }];
changedCar (event: any) {
   let car = event.target.value;
   console.log(car.color);
}

component.html

<select class="form-control" (change)="changedCar($event)" >
       <option value="">Select Car</option>
       <option *ngFor="let car of cars" [ngValue]="car">{{ {{car.name}} }}</option>
</select>
Abel Valdez
  • 2,368
  • 1
  • 16
  • 33
1

You could define a selectedCar property in your code and bind it to the select element with [(ngModel)]. In order to use Car objects as options, the option values must be set with [ngValue]. The first option will be selected by default if you set its value to the initial value of selectedCar, which is undefined in the code sample below.

Two way data binding ensures that selectedCar is synchronized with the selected item in the dropdown list, without having to use an event handler. If you want to do additional processing when the selection changes, you can handle the (ngModelChange) event.

See this stackblitz for a demo.

HTML:

<select class="form-control" [(ngModel)]="selectedCar">
  <option [ngValue]="undefined">Select a car</option>
  <option *ngFor="let car of cars" [ngValue]="car">{{car.name}}</option>
</select>

Code:

export class Car {
  name: string;
  color: string;
}
export class MyComponent {

  cars: Array<Car> = [
    { name: 'Jeep', color: 'black' },
    { name: 'Ferrari', color: 'red' },
    { name: 'Toyota', color: 'white' },
    { name: 'Ford', color: 'green' }
  ];

  selectedCar: Car;

  ...
}
ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
  • I am very sorry I didn't wanted to complicated my original post with the fact that my data set of the name/car is coming from an angular service. If you wouldn't mind further expanding your method for my exact situation I would greatly appreciate it. database.service.ts code: getCar(): Observable { const url = 'http://localhost:3000/car'; const data = ({ }); return this._http.post(url, data) .pipe( map((res) => { console.log(res); return res; }) ); } – user68288 May 11 '18 at 01:44
  • I am sorry, as I said I am very new. How would I use the async pipe? – user68288 May 11 '18 at 01:57
  • After reading the changes in the question, the async pipe does not apply because you subscribe to the observable (and `cars` should just be a normal array). The surprising thing in your code is that you use a POST request to get data. A GET request might be more appropriate. Can you see if `cars` is populated? If so, then the code in the answer should work. – ConnorsFan May 11 '18 at 02:01
  • I may have to try and convert the POST request to a GET it seems. When I do {{ car }} it shows in the console as [object Object] for every instance of a car in cars. – user68288 May 11 '18 at 02:19
  • Oops. I misread your comment. You can log the data in the observable callback: `this.databaseService.getCar().subscribe(cars => { console.log(cars); this.cars = cars; });`. – ConnorsFan May 11 '18 at 02:33
  • When I updated with that code the console shows all of the arrays so like {name: "Jeep", color: "Black"} etc. Is this good news? – user68288 May 11 '18 at 02:41
  • At that point, your data is basically equivalent to the data in the answer. You can declare `selectedCar` and use the HTML markup given in the answer. – ConnorsFan May 11 '18 at 02:44
  • I have it very close thanks to your help. Currently the console is working as desired but for some reason I am getting the following error: ): error TS2339: Property 'color' does not exist on type 'Car'. Current in my component I have the following around Car. import { Car} from './../database.service'; cars: Array; – user68288 May 11 '18 at 03:00
  • You should add `color: string` to the `Car` class definition in `database.service.ts`. I modified the answer to show you what it should look like. – ConnorsFan May 11 '18 at 03:04
  • WOW thank you! You are my favorite person on the planet right now. Everything is working with no errors! THANK YOU! – user68288 May 11 '18 at 03:13
0

Correct me if I am wrong, but as I understood from your question, the desired behaviour can be achieved by setting the value of your option tag to car instead of car.name. Therefore you will be passing the whole car object instead of the name only. So, the final code should look like <option *ngFor="let car of cars" value="car"> {{car.name}} </option>

vbrdnk
  • 1
  • 2
  • I am trying exactly this but I am getting the following in my console "undefined" versus black. I also tried doing a console.log(car) and it shows as: [object Object]. Any ideas? – user68288 May 10 '18 at 22:06
0

This is another example by sending a property and filtering the cars array.

component.ts

cars =[ {
      id: 1,
      brand: 'Jeep',
      color: 'black'
    },
    {
      id: 2,
      brand: 'Honda',
      color: 'blue'
    }];
changedCar (event: any) {
  this.selectedName = event.target.value;  
  let car = this.cars.find(x => x.name == this.selectedName);
  console.log(car.color);
}

component.html

<select class="form-control" (change)="changedCar($event)" >
       <option value="">Select Car</option>
       <option *ngFor="let car of cars" value="{{car.name}}">{{ {{car.name}} }}</option>
</select>

You can use id or name to filter data.

Abel Valdez
  • 2,368
  • 1
  • 16
  • 33
0

Change your code to this

<p>Select Car</p>
<select class="form-control" *ngFor="let car of cars" 
(change)="changedCar(car.name , car.color)" >
<option value="{{car.name}}">{{ {{car.name}} }}</option>
</select>

changedCar (name , color) {
  this.selectedName = name;
  this.selectedColor = color;
  console.log(selectedColor);
  console.log(selectedColor);
}