LIDOR SYSTEMS

Advanced User Interface Controls and Components

Add Context Menu to Angular Accordion

Created: 02 December 2015

Accordion directive by default doesn't have a context menu attached. Therefore, when an accordion header is right-clicked the default browser menu will appear. We can override this by creating a custom context menu for each accordion header, which will appear on right-click.

{{group.text}}

{{group.body}}

Accordion directive is part of IntegralUI Studio for Web
a suite of UI Components for development of web apps

In our demo, when accordion header is right-clicked, a menu will appear with several options.

Similar: Accordion Component for Angular 2

Create Context Menu for Accordion Headers

We will use the IntegralUI ContextMenu directive to create a custom menu. This directive will be attached to each accordion header, like this:

// A unique identifer for the Accordion

$scope.ctrlName = "ctrlSample";

 

// An object that holds accordion groups

$scope.groups = [

{

name: 'group1',

text: 'Group 1',

body: 'Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus magna felis sollicitudin mauris. Integer in mauris eu nibh euismod gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis risus a elit. Etiam tempor.'

},

{

name: 'group2',

text: 'Group 2',

body: 'Pellentesque malesuada nulla a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque nunc. Nullam arcu. Aliquam consequat.'

},

{

name: 'group3',

text: 'Group 3',

body: 'Fusce convallis, mauris imperdiet gravida bibendum, nisl turpis suscipit mauris, sed placerat ipsum urna sed risus. In convallis tellus a mauris. Curabitur non elit ut libero tristique sodales. Mauris a lacus. Donec mattis semper leo. In hac habitasse platea dictumst.'

}

];

 

// Initially 3 groups are visible

$scope.visibleGroups = 3;

<!DOCTYPE html>

<html>

<head>

<link rel="stylesheet" href="css/integralui.accordion.css" />

<link rel="stylesheet" href="css/integralui.contextmenu.css" />

<link rel="stylesheet" href="css/themes/theme-flat-blue.css" />

<script type="text/javascript" src="external/angular.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.accordion.min.js"></script>

<script type="text/javascript" src="js/angular.integralui.contextmenu.min.js"></script>

</head>

<body>

<div ng-app="appModule" ng-controller="appCtrl">

<iui-accordion name="{{ctrlName}}" class="directive" groups="groups" iui-contextmenu="groupMenu" group-added="onGroupAdded(e)">

<iui-accordion-group ng-repeat="group in groups" name="{{group.name}}">

<iui-accordion-header iui-contextmenu="groupMenu">

{{group.text}}

</iui-accordion-header>

<p class="custom-content">{{group.body}}</p>

</iui-accordion-group>

</iui-accordion>

</div>

</body>

</html>

.custom-content

{

margin: 0;

padding: 5px;

}

.iui-contextmenu-block

{

border-radius: 0;

padding: 2px;

}

.icons

{

background-image: url(../resources/icons.png);

background-repeat: no-repeat;

display: inline-block;

overflow: hidden;

padding: 0 !important;

margin: 0 5px 0 0;

width: 16px;

height: 16px;

vertical-align: middle;

}

.check-mark

{

background-position: -96px -48px;

}

As it can be seen from code above, an object called groupMenu is applied to the context menu directive. This object will hold all menu items and events.

In our example, we will add menu options that add or remove new groups to the accordion and options that can change their visibility.

Add/Remove Groups using Menu Options

We can add or remove accordion groups using the context menu options. In our example the following operations are available:

  • Add Group - will add a new accordion group at the end
  • Insert Group Before - will add a new accordion group before currently selected group
  • Insert Group After - will add a new accordion group after currently selected group
  • Remove Group - will remove the currently selected group

Related: Add or Remove Groups in Accordion for AngularJS

Whenever an option is selected, the itemClick event is fired. Each menu item has a different key so that we can distinguish which one is clicked. By handling this event, we can add a specific operation depending on which option is selected.

var groupCount = $scope.groups.length;

 

// Gets the currently selected group in the accordion

var getCurrentSelection = function(){

return $ctrlService.selectedGroup($scope.ctrlName);

}

 

// Creates a new accordion group

var createNewGroup = function(){

groupCount++;

return { name: "group" + groupCount, text: "Group " + groupCount, body: 'Group ' + groupCount + " Content" };

}

 

// Default menu options for adding groups

var defaultMenuItems = [

{ text: 'Add Group', key: 'ADD_GROUP' },

{ text: 'Insert Group Before', key: 'INSERT_GROUP_BEFORE' },

{ text: 'Insert Group After', key: 'INSERT_GROUP_AFTER' },

{ text: 'Remove Group', key: 'REMOVE_GROUP', enabled: $scope.visibleGroups > 0 }

];

 

// Menu object that holds all menu options for the accordion context menu

$scope.groupMenu = {

itemIcon: 'icons empty',

items: defaultMenuItems,

itemClick: function(e){

if (e.item){

$ctrlService.suspendLayout($scope.ctrlName);

 

var selGroup = getCurrentSelection();

 

switch (e.item.key){

case 'ADD_GROUP':

$ctrlService.addGroup($scope.ctrlName, createNewGroup());

break;

 

case 'INSERT_GROUP_BEFORE':

$ctrlService.insertGroupBefore($scope.ctrlName, createNewGroup(), getCurrentSelection());

break;

 

case 'INSERT_GROUP_AFTER':

$ctrlService.insertGroupAfter($scope.ctrlName, createNewGroup(), getCurrentSelection());

break;

 

case 'REMOVE_GROUP':

$ctrlService.removeGroup($scope.ctrlName, getCurrentSelection());

break;

}

 

$ctrlService.resumeLayout($scope.ctrlName);

}

}

}

 

// When new group is added it is also selected

$scope.onGroupAdded = function(e){

$ctrlService.selectedGroup($scope.ctrlName, e.obj);

}

In our case, adding and remove operations are simple because we are using some of built-in methods available.

Change Accordion Group Visibility

For group visibility, we are using a dynamic menu. Meaning, whenever an accordion group changes its visibility status, the menu is also updated. When some of these menu options are clicked, the corresponding group will become visible or hidden.

// Menu object that holds all menu options for the accordion context menu

// In this case also adds the menu options for group visibility

$scope.groupMenu = {

itemIcon: 'icons empty',

items: [],

itemClick: function(e){

if (e.item){

$ctrlService.suspendLayout($scope.ctrlName);

 

var selGroup = getCurrentSelection();

 

switch (e.item.key){

 

// Place here the menu options for add/remove of groups

 

default:

var index = visibilityMenuItems.indexOf(e.item);

if (index >= 0 && index < $scope.groups.length){

$scope.groups[index].visible = $scope.groups[index].visible == undefined ? false : !$scope.groups[index].visible;

 

// Make sure correct group is selected

if ($scope.groups[index].visible != false)

$ctrlService.selectedGroup($scope.ctrlName, $scope.groups[index]);

else if ($scope.groups[index] == selGroup)

$ctrlService.selectedGroup($scope.ctrlName, getNextGroup(selGroup));

}

break;

}

 

updateMenu();

 

$ctrlService.resumeLayout($scope.ctrlName);

}

}

}

We are also updating the currently selected group, so that there is always at least one accordion group selected and opened.

var visibilityMenuItems = [];

 

var getCheckIcon = function(group){

return group.visible != false ? 'icons check-mark' : null;

}

 

// Updates the options in context menu

var updateMenu = function(){

$scope.groupMenu.items.length = 0;

$scope.visibleGroups = 0;

 

for (var i = 0; i < defaultMenuItems.length; i++)

$scope.groupMenu.items.push(defaultMenuItems[i]);

 

visibilityMenuItems.length = 0;

 

var menuItem = { type: "separator" };

if ($scope.groups.length > 0){

$scope.groupMenu.items.push(menuItem);

 

for (var i = 0; i < $scope.groups.length; i++){

menuItem = {

icon: getCheckIcon($scope.groups[i]),

text: $scope.groups[i].text

}

 

if ($scope.groups[i].visible != false)

$scope.visibleGroups++;

 

visibilityMenuItems.push(menuItem);

$scope.groupMenu.items.push(menuItem);

}

}

 

$scope.groupMenu.items[1].enabled = $scope.visibleGroups > 0;

$scope.groupMenu.items[2].enabled = $scope.visibleGroups > 0;

$scope.groupMenu.items[3].enabled = $scope.visibleGroups > 0;

}

 

// Watch whether there are no visible groups and show a frame in accordion space

$scope.$watch("visibleGroups", function(newValue){

if (newValue == 0){

$scope.ctrlBackground = 'white';

$scope.ctrlBorder = 'thin solid gray';

}

else {

$scope.ctrlBackground = 'transparent';

$scope.ctrlBorder = 'thin solid transparent';

}

});

Note Each accordion group can display a different context menu. To keep it simple, in our case all groups have the same context menu.

Conclusion

Adding a custom context menu to the groups in Angular Accordion directive is easy. By using the context menu directive, we can create a menu with custom functionality, which will override the default browser menu. Each accordion group or in fact accordion as a whole can have a different and custom context menu attached.

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.