1

When creating a select control, with options that may be pulled from a database, it seems customary to put an ngFor on the template side to render the options.

What I want to do is instead have a loop on the component side that builds a string with the options:

for (var i = 0; i < 20; i++) {
    this.selectOptions += "<option value=" + i + ">" + i + "</option> ";
}

Then in the template side of something like this:

<select>
    {{selectOptions}}
</select>

The reason I want to do this is I have some nested loops in a complex UI, and several selects that have the same options. Once rendered the options do not change.

I want to get rid of all the ngFors that are running in order to try to speed up my UI. There are other things I need to do as well, but this is something that I think could help. Then the loops for the options only have to run 1 time instead of over and over.

Sébastien
  • 11,860
  • 11
  • 58
  • 78

4 Answers4

2

Try using [innerHTML] along with the DomSanitizer:

https://stackblitz.com/edit/angular-kpkk4v?file=app%2Fapp.component.ts

Component:

export class AppComponent  {
  options = '<option value=1>1</option><option value=1>1</option>';
  optionsHTML: any;

  constructor(private sanitizer: DomSanitizer) {
    this.optionsHTML = this.sanitizer.bypassSecurityTrustHtml(this.options);
  }
}

Template:

<select [innerHTML]="optionsHTML"></select>

Note:

You need to sanitize the HTML in order for angular to render it, otherwise angular will remove the HTML and all you get is a string rendering <select>11</select>

Sonu Kapoor
  • 1,567
  • 3
  • 16
  • 34
1

Untested but I think you could use innerHTML like this:

<select [innerHTML]="selectOptions"></select>
Sébastien
  • 11,860
  • 11
  • 58
  • 78
1

As shown here it seems that

<select [innerHTML]="selectOptions"></select>

.. is what you're looking for. It is also said to work currently in version 5.0.2

fingeron
  • 1,152
  • 1
  • 9
  • 20
0

Every one is telling you to use the [innerHTML] attribute : they're wrong.

And you are not going on the right path : you should use iterations in your HTML, not in your component's logic.

Why is that ?

Because when you use [innerHTML], you actually create just a string, that isn't related in any way to Angular. Furthermore, reading your code will become difficult, because you will have to switch from your HTML to your TS to see what you're doing.

The solution

You said you had several complicated loops and once set, the options should not move ? That's perfect for Angular !

You can create a new component that will handle your selects :

@Component({
  selector: 'app-my-select',
  template: `
  <select [(ngModel)]="mySelect" (change)="change.emit(mySelect)" *ngIf="options">
  <option *ngFor="let option of options" [value]="option">{{ option }}</option>
  </select>
  `,
  styleUrls: ['./my-select.scss']
})
export class MySelectComponent implements OnInit {

  @Input() options: any[];
  @Output() change: EventEmitter<any> = new EventEmitter();

  mySelect: any; 

  constructor() {}

  ngOnInit() {
    console.log('options are ' + this.options);
    this.mySelect = this.options[0];
  }
}

Now, in your other components, you can simply do

<app-my-select [options]="yourOptions" (change)="doSomething($event)"></app-my-select>
Community
  • 1
  • 1