Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select dropdown component that supports optgroup in Angular 2

Tags:

angular

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')
        ]),
    ];
}
like image 793
ajbeaven Avatar asked Mar 12 '23 17:03

ajbeaven


1 Answers

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

like image 182
yurzui Avatar answered Mar 19 '23 07:03

yurzui