LIDOR SYSTEMS

Advanced User Interface Controls and Components

Overview of IntegralUI Menu for Angular 2

Created: 20 September 2016

Updated: 21 December 2016

IntegralUI Menu is a native Angular 2 component that allows you to create static and dynamic menus. You can populate the menu directly in your HTML or using a custom data source, either locally or remotely. In following sections, you can find details about various features available in the Menu component.

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

In above demonstration, we have a menu with four root menu items. Each menu has an icon, label and expand mark if there are child items. Whenever mouse cursor hovers over a menu item, an animation will start showing a window with child items. By clicking on menu item, a message box will appear, stating menu item that was clicked.

How to Use IntegralUI Menu in Angular 2

In order to use the Menu component in your app, you need to do the following:

  • Place the Menu using the iui-menu tag name
  • Add menu items using iui-menuitem tag name
  • Use property bindings or add custom HTML elements as item content
  • Connect the Menu to your data source

//

// main.ts file

//

 

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

 

const platform = platformBrowserDynamic();

platform.bootstrapModule(AppModule);

 

 

 

//

// app.module.ts file

//

 

import { NgModule } from '@angular/core';

import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

import { IntegralUIModule } from './integralui/integralui.module';

 

@NgModule({

imports: [ BrowserModule, IntegralUIModule ],

declarations: [ AppComponent ],

bootstrap: [ AppComponent ]

})

export class AppModule { }

 

 

 

//

// app.component.ts file

//

 

import { Component, ViewEncapsulation } from '@angular/core';

 

@Component({

selector: 'iui-app',

templateUrl: 'app.template.html',

styleUrls: ['menu-overview.css'],

encapsulation: ViewEncapsulation.None

})

export class AppComponent {

// An Array object that holds all item objects shown in Menu

// It is set as a list of any custom objects, you can use any custom fields and bind them with Menu using its properties

public items: Array;

 

// Get a reference of application view

@ViewChild('application', {read: ViewContainerRef}) applicationRef: ViewContainerRef;

 

// Initialize items in component constructor

constructor(){

this.items = [

{

id: 1,

text: "File",

icon: "",

items: [

{

id: 11,

pid: 1,

text: "New",

icon: "icons-medium new-document",

items: [

{ id: 111, pid: 11, text: "Project", icon: "icons-medium empty" },

{ id: 112, pid: 11, text: "Window", icon: "icons-medium empty" }

]

},

{ id: 12, pid: 1, text: "Open", icon: "icons-medium empty" },

{ id: 13, pid: 1, text: "Save As...", icon: "icons-medium save" },

{ id: 14, pid: 1, text: "Save All", icon: "icons-medium empty" },

{ id: 15, pid: 1, type: "separator" },

{ id: 16, pid: 1, text: "Page Setup", icon: "icons-medium empty" },

{ id: 17, pid: 1, text: "Print", icon: "icons-medium print" },

{ id: 18, pid: 1, type: "separator" },

{ id: 19, pid: 1, text: "Exit", icon: "icons-medium empty" },

]

},

{

id: 2,

text: "Edit",

icon: "",

items: [

{ id: 21, pid: 2, text: "Undo", icon: "icons-medium empty" },

{ id: 22, pid: 2, text: "Redo", icon: "icons-medium empty" },

{ id: 23, pid: 2, type: "separator" },

{ id: 24, pid: 2, text: "Cut", icon: "icons-medium empty" },

{ id: 25, pid: 2, text: "Copy", icon: "icons-medium copy" },

{ id: 26, pid: 2, text: "Paste", icon: "icons-medium empty" },

{ id: 27, pid: 2, text: "Delete", icon: "icons-medium delete-document" },

]

},

{

id: 3,

text: "View",

icon: "",

items: [

{ id: 31, pid: 3, text: "Print Layout", icon: "icons-medium empty" },

{

id: 32,

pid: 3,

text: "Zoom",

icon: "icons-medium zoom",

items: [

{ id: 321, pid: 32, text: "Zoom In", icon: "icons-medium zoom-in" },

{ id: 322, pid: 32, text: "Zoom Out", icon: "icons-medium zoom-out" },

{ id: 323, pid: 32, type: "separator" },

{ id: 324, pid: 32, text: "Restore", icon: "icons-medium empty" }

]

},

{ id: 33, pid: 3, type: "separator" },

{ id: 34, pid: 3, text: "Full Screen", icon: "icons-medium empty" },

]

},

{

id: 4,

text: "Help",

icon: "",

items: [

{ id: 41, pid: 4, text: "Search", icon: "icons-medium empty" },

{ id: 42, pid: 4, text: "Documents", icon: "icons-medium empty" },

{ id: 43, pid: 4, type: "separator" },

{ id: 44, pid: 4, text: "About", icon: "icons-medium empty" },

]

}

];

}

 

menuItemClick(e){

if (e.item.pid)

alert("Menu item: " + e.item.text + " is clicked.");

}

 

}

 

bootstrap(AppComponent);

//

// app.template.html file

//

 

<iui-menu [appRef]="applicationRef" [items]="items" (itemClick)="menuItemClick($event)">

<iui-menuitem *ngFor="let item of items" [icon]="item.icon" [text]="item.text" [data]="item" [items]="item.items">

<iui-menuitem *ngFor="let childItem of item.items" [icon]="childItem.icon" [text]="childItem.text" [data]="childItem" [items]="childItem.items">

<iui-menuitem *ngFor="let childItem2 of childItem.items" [icon]="childItem2.icon" [text]="childItem2.text" [data]="childItem2">

</iui-menuitem>

</iui-menuitem>

</iui-menuitem>

</iui-menu>

/*

menu-overview.css file

*/

 

.icons-medium

{

background: url(../resources/icons-x24.png) no-repeat 0 0;

display: inline-block;

overflow: hidden;

padding: 0;

margin: 0 3px 0 0;

width: 24px;

height: 24px;

vertical-align: middle;

}

.empty-doc

{

background-position: -24px -48px;

}

.new-document

{

background-position: 0 -96px;

}

.delete-document

{

background-position: -24px -96px;

}

.copy

{

background-position: -48px -96px;

}

.save

{

background-position: -72px -96px;

}

.print

{

background-position: -96px -96px;

}

.zoom

{

background-position: -120px -96px;

}

.zoom-in

{

background-position: -144px -96px;

}

.zoom-out

{

background-position: -168px -96px;

}

You can either set content of menu items using built-in properties: icon and text, or add your own HTML elements as content of menu item. In addition, using the ngIf directive, you can specify a condition by which item content is created. In this way you can have menu items with different layout.

<iui-menuitem *ngFor="let item of items" [data]="item">

<span class="{{item.icon}}"></span>

<span>{{item.text}}</span>

</iui-menuitem>

In order to populate the menu, you can use any custom data source. When creating your data structure, make sure that each item has at least these fields set:

  • icon - specifies the icon that is displayed in front of item label
  • id - specifies a unique identifier for the item
  • items - holds a reference to the list of child items, used for multi-leveling
  • pid - specifies the identifier of parent item of this item
  • text - specifies the item label
  • type - specifies the item type

Note Item type can contain one of the following values: 'item' or 'separator'. By default, all items are of 'item' type, so this value is not necessary.

Supported Properties

All properties of the Menu component can be set using a separate attribute that is linked to an object in your application scope or to a specified value.

Here is a list of available properties:

  • appRef - holds a reference to application view
  • controlStyle - specifies an object that holds names for custom CSS classes
  • dataFields - specifies an object that map the fields names from data source to the ones used by the Menu
  • items - holds a reference to the list of items defined in your application component

Data Binding in Menu

When you have a custom data source that may differ from internal data settings of the Menu component, you can use data binding which will match the names of data fields in your data source with those used by the menu.

By specifying the items property to point to your data object, along with dataFields property that holds an object that maps the names of fields in the data object, you can populate the Menu using any kind of custom data source.

This feature is also usable when you need to load data on demand in the Menu, from a remote data source.

Supported Events

When interacting with the Menu component, depending on the action, a corresponding event is fired. For example clicking an item will fire itemClick event, opening or closing of the menu will fire the opened or closed events, etc.

Here is a list of available events:

  • closed - occurs when menu is closed
  • clear - occurs when all items are removed from the Menu
  • itemAdded - occurs when new item is added to the Menu
  • itemAdding - occurs before item is added
  • itemClick - occurs when item header is clicked
  • itemRemoved - occurs when item is removed from the Menu
  • itemRemoving - occurs before item is removed
  • opened - occurs after animation completes and menu is opened

By handling these events in your code, you can add custom actions that may alter the default behavior of the Menu component. For example, by handling the itemClick event, you can add a specific action that will execute when item is clicked:

//

// app.component.ts file

//

 

export class AppComponent {

// An Array object that holds all item objects shown in Menu

private data: Array;

 

// Initialize items in component constructor

constructor(){

this.data = [];

}

 

// Fired whenever a menu item is clicked

menuItemClick(e){

if (e.item.pid)

alert("Menu item: " + e.item.text + " is clicked.");

}

}

 

bootstrap(AppComponent);

//

// app.template.html file

//

 

<iui-menu [items]="items" (itemClick)="menuItemClick($event)">

<iui-menuitem *ngFor="let item of items" [data]="item">

<span class="{{item.icon}}"></span>

<span>{{item.text}}</span>

</iui-menuitem>

</iui-menu>

In this example, the same event handler is used for all items. Whenever a menu item is clicked, a message window will popup stating the name of the menu item.

How to Add/Remove Items Dynamically

In some cases, you may need to add new items or remove existing items in the Menu during run-time. For this purpose, there are built-in methods available that allow you to change the structure of the Menu:

//

// app.component.ts file

//

 

export class AppComponent {

// An Array object that holds all item objects shown in Menu

private data: Array;

 

// Get a reference to the Menu component using a variable set in HTML

@ViewChild('menu') menu: IntegralUIMenu;

 

// Initialize items in component constructor

constructor(){

this.data = [];

}

 

// Adds a new item to the end of the Menu

addItem(){

this.menu.addItem({ text: "Item " + (this.data.length+1).toString() });

}

 

// Fired whenever a new item is added to the Menu

itemAddedEvent(e){

if (e.item)

console.log("itemAdded: " + e.item.text);

}

}

 

bootstrap(AppComponent);

//

// app.template.html file

//

 

<iui-menu [items]="data" (itemAdded)="itemAddedEvent($event)" #menu>

<iui-menuitem *ngFor="let item of items" [text]="item.text" [data]="item"></iui-menuitem>

</iui-menu>

In above code, we are adding a new item with some items using the addItem method. To access this method, at first we need to get a reference to the Menu component. In HTML we are adding the #menu variable, which is used to locate the Menu within your application component.

After we have a reference to the Menu component, we can get access to all public methods available:

  • addItem - inserts a new item at the end of Menu
  • clearItems - removes all items from the Menu
  • findItemById - searches through tree hierarchy for an item that matches specified id
  • findItemByText - searches through tree hierarchy for an item that matches specified text
  • insertItemAfter - inserts a new item in a position after specified item
  • insertItemBefore - inserts a new item in a position before specified item
  • insertItemAt - inserts a new item at specified position
  • removeItem - removes the specified item from the Menu

How to Customize the Menu Appearance

Each part of IntegralUI Menu component is fully customizable. There are different CSS classes for each component part. Although changing the attributes of built-in classes is possible, you can completely override them using the controlStyle property.

The controlStyle property accepts an object that holds all or partial list of CSS class names that will override the default CSS class names. For each component part, a different CSS class governs its appearance. This allows you to specify a set of different CSS classes for each component part and alter the appearance of the Menu in whole. In this way, you can make it more suitable for your application requirements.

Conclusion

IntegralUI Menu component allows you to create static and dynamic menus in your web pages. You can use an arbitrary data to populate the menu, either from local or remote data source. in addition, you can customize the appearance of the menu by specifying custom CSS classes to the controlStyle property.

By default, each item contains an icon and a label. By adding custom HTML elements or other Angular components as content of menu items, you can create menus that have different elements arranged in custom layouts.

Currently this component is in BETA. The Menu component will be part of IntegralUI Studio for Web. Here you can check out different features of existing components.

Did you Like this Article?


Enter your e-mail address below and you will receive latest articles as well as news on upcoming events and special offers.