LIDOR SYSTEMS

Advanced User Interface Controls and Components

Items with ComboBox in Angular TreeView

Created: 23 Apr 2018

The item template in IntegralUI TreeView component allows you to place any HTML element or Angular components and arrange them in custom layouts. In this article, you will learn how to add a ComboBox to each item in the TreeView. Using the combo box you can change the item value on demand.

TreeView component is part of IntegralUI Web
a suite of UI Components for development of web apps

If you have any questions, don't hesitate to contact us at support@lidorsystems.com

In this example, each TreeView item has a ComboBox, shown after its label. Initially, the combo box is hidden and an underlined label is shown instead.

The underlined label represents a value that can be changed. When item is clicked, an editor (in this case a ComboBox) replaces the label. By selecting different options from the combo list, you can change the item value. After value is changed, the combo box becomes again hidden, and the underlined label appears.

All items have a combo box, except for the item labeled 'Copy Count' which uses a NumericUpDown component as an editor.

How to Add a ComboBox to TreeView Items in Angular

In this example, initially two labels represent the item. The second label is underlined to show to the user that it can be changed during run-time. As an editor, a ComboBox is shown whenever item is clicked. This combo shows a dropdown list with options specific to the item.

To add a ComboBox to the item, you need to add a combo box component inside the item template. However, because not all items will contain a combo box (parent items are excluded), you need to use some kind of an identifier and change the template content based on that value.

In this case, the combo box will only appear when item is clicked and it is not a parent. This is handled by checking whether the item is equal to the currently active item, which is set whenever item is clicked. To set which item is active, a handler to mousedown event is added in top element of the item template.

public activeItem: any = null;

public comboStyle: any = {
    general: {
        normal: 'trw-combo-cmb'
    },
    header: {
        general: {
            normal: 'trw-combo-cmb-header',
            hovered: 'trw-combo-cmb-header-hovered'
        }
    }
}

itemClicked(e: any, item: any){
    if (item.items)
        this.activeItem = null;
    else
        this.activeItem = item;
}
                            
<iui-treeview [items]="data" [controlStyle]="treeStyle" [virtualMode]="true" [itemDisplay]="0" #treeview>
    <ng-template let-item>
        <div (mousedown)="itemClicked($event, item)">
            <span [ngClass]="getItemIcon(item)"></span>
            <span class="trw-combo-item-label">{{item.text}}</span>
            <span *ngIf="item!=activeItem" [ngSwitch]="item.id">
                <span *ngSwitchCase="12">
                    <span class="trw-combo-item-value">
                        {{item.value}} 
                        <span *ngIf="item.value == 1">Copy</span>
                        <span *ngIf="item.value > 1">Copies</span>
                    </span>
                </span>
                <span *ngSwitchDefault>
                    <span class="trw-combo-item-value" >{{item.value}}</span>
                </span>
            </span>
            <span *ngIf="item==activeItem" [ngSwitch]="item.id">
                <span *ngSwitchCase="12">
                    <iui-numeric-updown [controlStyle]="numUpDownStyle" [(ngModel)]="item.value"></iui-numeric-updown>
                </span>
                <span *ngSwitchDefault>
                    <iui-combobox [items]="item.combo" [controlStyle]="comboStyle" [size]="{ width: item.comboWidth }" [maxDropDownItems]="5" [integralHeight]="true" [selectedItem]="getComboSelection(item)" (selectedItemChanged)="onComboSelectionChanged($event, item)" (dropDownClosed)="onComboClosed($event)">
                        <iui-item *ngFor="let item of item.combo" [text]="item.text"></iui-item>
                    </iui-combobox>
                </span>
            </span>
        </div>
    </ng-template>
</iui-treeview>
                            
.trw-combo-cmb
{
    display: inline-block;
    margin: 0;
    vertical-align: top;
}
.trw-combo-cmb-header, .trw-combo-cmb-header-hovered
{
    border: thin solid #cecece;
    padding: 0;
}
.trw-combo-cmb-header .iui-header-expand-box-arrow
{
    margin: 2px;
}
                          

Some items can have a different content; in this example the 'Copy Count' item uses a NumericUpDown component, because the underlined label value displays a numeric value. For this purpose, the template should have some conditions set that alter the item appearance. In this case, the item id is used to determine the item type.

public numUpDownStyle: any = {
    general: { normal: 'trw-combo-num' }
}
                            
<iui-treeview [items]="data" [controlStyle]="treeStyle" [virtualMode]="true" [itemDisplay]="0" #treeview>
    <ng-template let-item>
        <div (mousedown)="itemClicked($event, item)">
            <span [ngClass]="getItemIcon(item)"></span>
            <span class="trw-combo-item-label">{{item.text}}</span>
            <span *ngIf="item!=activeItem" [ngSwitch]="item.id">
                <span *ngSwitchCase="12">
                    <span class="trw-combo-item-value">
                        {{item.value}} 
                        <span *ngIf="item.value == 1">Copy</span>
                        <span *ngIf="item.value > 1">Copies</span>
                    </span>
                </span>
                <span *ngSwitchDefault>
                    <span class="trw-combo-item-value" >{{item.value}}</span>
                </span>
            </span>
            <span *ngIf="item==activeItem" [ngSwitch]="item.id">
                <span *ngSwitchCase="12">
                    <iui-numeric-updown [controlStyle]="numUpDownStyle" [(ngModel)]="item.value"></iui-numeric-updown>
                </span>
                <span *ngSwitchDefault>
                    <iui-combobox [items]="item.combo" [controlStyle]="comboStyle" [size]="{ width: item.comboWidth }" [maxDropDownItems]="5" [integralHeight]="true" [selectedItem]="getComboSelection(item)" (selectedItemChanged)="onComboSelectionChanged($event, item)" (dropDownClosed)="onComboClosed($event)">
                        <iui-item *ngFor="let item of item.combo" [text]="item.text"></iui-item>
                    </iui-combobox>
                </span>
            </span>
        </div>
    </ng-template>
</iui-treeview>
                            
.trw-combo-num
{
    display: inline-block;
    padding: 0;
    vertical-align: top;
    width: 50px;
}
                          

Each item can display a ComboBox with different options. To handle this, you can add an array of objects to the item object, and link it with the combo box items property. Based on data set, when combo box appears it will contain only the options from item combo list.

this.data = [
    { 
        id: 1,
        text: "Paper/Output",
        icon: "trw-combo-icons-medium trw-combo-icon-paper",
        items: [
            { 
                id: 11, 
                pid: 1, 
                text: "Paper Size: ", 
                value: "Letter",
                combo: [
                    { text: "16K" },
                    { text: "A4" },
                    { text: "A5" },
                    { text: "A6" },
                    { text: "B5" },
                    { text: "Envelope #10" },
                    { text: "Envelope B5" },
                    { text: "Envelope C5" },
                    { text: "Envelope DL" },
                    { text: "Envelope Monarch" },
                    { text: "Executive" },
                    { text: "Folio" },
                    { text: "Legal" },
                    { text: "Letter" }
                ],
                comboWidth: 180
            },
            { id: 12, pid: 1, text: "Copy Count: ", value: 1, tag: "Copy" }
        ]
    },

   // Additonal data is placed here
];
                            

Once an option is selected from the combo list, you need to update the item value. This is handled by the selectedItemChanged event, where you can change the item value by the selected item text from the combo box.

onComboSelectionChanged(e: any, item: any){
    if (e.item)
        item.value = e.item.text;
} 

getComboSelection(item: any){
    let found: any = null;

    if (item.combo)
        for (let i = 0; i < item.combo.length; i++){
            if (item.combo[i].text == item.value){
                found = item.combo[i];
                break;
            }
        }

    return found;
}                            

Note Item value is used to display the text to the second label, set in the item template. So any change to the item.value field is automatically applied to the item label.

To hide the combo box once the option is selected, and to show again the underlined label with value from selected option, you can handle the dropDownClosed event. This event is fired whenever the dropdown list of the combo box closes. By resetting the activeItem variable to null, the item template is automatically changed.

onComboClosed(e: any){
    this.activeItem = null;
}                            

As a result of all this changes to the item template, you have a TreeView where items display a different value from user interaction. In similar way like it is presented here, you can use any other editor to change the item content on demand. For example, you can edit items by showing a custom text editor.

Conclusion

Each item in TreeView component for Angular can have a different content, by placing custom HTML elements inside the item template. In case you need to change item value during run-time, you can use a ComboBox component and provide a list of options to the user. Each item can display a combo box with different options. In addition, you can hide the combo box initially and to appear only when required.

You can use this sample as a guideline to create your own solution, and further extend it to match your application requirements.

The TreeView component is part of IntegralUI Web.

Newsletter


Sign-up to our newsletter and you will receive news on upcoming events, latest articles, samples and special offers.
Name: Email: *
*By checking this box, I agree to receive a newsletter from Lidor Systems in accordance with the Privacy Policy. I understand that I can unsubscribe from these communications at any time by clicking on the unsubscribe link in all emails.