I'm attempting to create an Angular 2 component that is responsible for rendering a select
form control and I'm having some trouble trying to make it support optgroup
.
When rendering, I need to be able to switch between an optgroup
and an option
element depending on whether the item has children or not. I'm attempting to use a template
tag in order to iterate these items, but it looks like this isn't supported inside a select
. I also tried adding *ngIf
and *ngFor
on the same element but that isn't supported either.
How do I create a select
with optgroup
in Angular 2?
Plunkr demo
form-select.component.js
import { Component, Input, Output, EventEmitter, ElementRef } from '@angular/core';
import { CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle } from '@angular/common';
export class FormSelectOption {
id: string;
text: string;
children: FormSelectOption[];
constructor(id: string, text: string, children: FormSelectOption[]) {
this.id = id;
this.text = text;
this.children = children;
}
}
@Component({
selector: 'form-select',
template: `
<select>
<!-- WORKING -->
<option *ngFor="let item of items" (click)="select(item.id)">{{item.text}}</option>
<!-- NOT WORKING -->
<!--<template *ngFor="let item of items">
<optgroup *ngIf="item.children" label="{{item.text}}">
<option *ngFor="let child of item.children" (click)="select(child.id)">{{child.text}}</option>
</optgroup>
<option *ngIf="!item.children" (click)="select(item.id)">{{item.text}}</option>
</template>-->
</select>
`
})
export class FormSelectComponent {
@Input()
items: FormSelectOption[];
@Input()
selectedValue: string[];
@Output()
valueChange: EventEmitter<any>;
constructor(private elementRef: ElementRef) {
this.valueChange = new EventEmitter<any>();
}
select(id) {
this.valueChange.emit(id);
}
}
app.ts
//our root app component
import {Component} from '@angular/core'
import {FormSelectComponent, FormSelectOption} from './form-select.component';
@Component({
selector: 'my-app',
template: `
<form-select [items]="things" [selectedValue]="selectedThing"></form-select>
`,
directives: [FormSelectComponent],
})
export class App {
selectedThing = '1';
things = [
new FormSelectOption('1', 'Fruit', [
new FormSelectOption('2', 'Bananas'),
new FormSelectOption('3', 'Apples'),
new FormSelectOption('4', 'Oranges')
]),
new FormSelectOption('5', 'Countries', [
new FormSelectOption('6', 'England'),
new FormSelectOption('7', 'New Zealand')
]),
new FormSelectOption('8', 'Shapes', [
new FormSelectOption('9', 'Square')
]),
];
}
Try the following:
<ng-template ngFor let-item [ngForOf]="items">
<optgroup *ngIf="item.children" label="{{item.text}}">
<option *ngFor="let child of item.children" (click)="select(child.id)">
{{child.text}}
</option>
</optgroup>
<option *ngIf="!item.children" (click)="select(item.id)">{{item.text}}</option>
</ng-template>
Plunker
Syntax ngFor:
<li *ngFor="let item of items; let i = index">...</li>
<li template="ngFor let item of items; let i = index">...</li>
<ng-template ngFor let-item [ngForOf]="items" let-i="index"><li>...</li></ng-template>
https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html#!#syntax
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With