3

I'm using the MEAN stack (Angular 6) and I'm still looking for the best way to build a custom and reusable <select> form control which uses an Array of strings returned from the BE to generate all <option> tags. Let's say for example we have 3 materials wood, metal and plastic and the returned Array can be one of the following (stored in the materials variable):

(in my example.component.ts)

form = new FormGroup({
  'material' = new FormControl('')
});

get material() {return this.form.get('material');}

materials = [
  {
    key: "mat_wood",
    value: "Wood"
  },
  {
    key: "mat_metal",
    value: "Metal"
  },
  {
    key: "mat_plastic",
    value: "Plastic"
  }
]

or

(in my example.component.ts)

form = new FormGroup({
  'material' = new FormControl('')
});

get material() {return this.form.get('material');}

materials = [
  {"mat_wood": "Wood"},
  {"mat_metal": "Metal"},
  {"mat_plastic": "Plastic"}
]

and we have this HTML structure:

(in my example.component.html)

<form [formGroup]="form">
  <div class="select-wrap">
    <span class="select-value">{{}}</span>

    <select formControlName="material">
      <option *ngFor="let mat of materials" value="{{}}">{{}}</option>
    </select>
  </div>
</form>

Which eventually has to be compiled to this:

  <select formControlName="material">
    <option value="mat_wood">Wood</option>
    <option value="mat_metal">Metal</option>
    <option value="mat_plastic">Plastic</option>
  </select>

Here we have a classical example of a custom select structure. The <span class="select-value"> displays the selected option's text to the user. The <select> has opacity set to 0 and is positioned on top of the <span>, so when the user clicks, he clicks on it and activates it.

For each option I need to put the mat_[something] in the value attribute and the readable Something as text in the option, just like in the example above:
<option value="mat_wood">Wood</option>.

Question is: How can I put the selected option text inside the <span>? I'm looking for a reusable way of doing it.


EDIT:
Looking at the first answer shows (and I forgot to mention) that using a template variable does the job. But if we have an enclosing *ngFor loop that generates multiple selects, then we need to have dynamically generated template variables. Is that even possible?

Andi Aleksandrov
  • 443
  • 2
  • 6
  • 16

2 Answers2

2

One way is you could refer to select as template variable say mySelect.

<select #mySelect formControlName="material">
  <option value="mat_wood">Wood</option>
  <option value="mat_metal">Metal</option>
  <option value="mat_plastic">Plastic</option>
</select>

And refer to its options.text property like this. {{ mySelect && mySelect.selectedIndex > -1 ? mySelect.options[mySelect.selectedIndex].text : ''}} inside your span element.

You can read about template variables here

kiranghule27
  • 439
  • 1
  • 7
  • 20
  • Hi, thank you for replying. I've tried that method but it fails when your select is part of a *ngFor loop. I don't think there's a way of generating dynamic template variables in that case, is there? – Andi Aleksandrov Jan 04 '19 at 10:44
  • Turns out it does work even in an ngFor loop. I've posted an answer with a link to an example. Thanks for making me try this approach again :) I guess I messed up the previous time. – Andi Aleksandrov Jan 04 '19 at 13:26
-2

Try this example for dynamic option

In Html

<mat-form-field>
  <mat-select placeholder="Select"    [(value)]="selected">
    <mat-option *ngFor="let data of materials" [value]="getKey(data)">{{getValue(data)}}</mat-option>
  </mat-select>
</mat-form-field>

<p>You selected: {{selected}}</p>

In TS

@Component({
  selector: 'select-value-binding-example',
  templateUrl: 'select-value-binding-example.html',
  styleUrls: ['select-value-binding-example.css'],
})
export class SelectValueBindingExample {
  selected = 'option2';
  materials = [
  {"mat_wood": "Wood"},
  {"mat_metal": "Metal"},
  {"mat_plastic": "Plastic"}
]
getValue(obj)
{
return obj[Object.keys(obj)[0]]
}
getKey(obj)
{
return Object.keys(obj)[0]
}
checkValue()
{
 console.log( this["mySelect"])
}
}
Satheesh
  • 171
  • 6
  • does this work in Angular 9? I can't get the "getValue()" or "getKey()" methods to return the correct values. – Cwinds Apr 03 '22 at 01:25