{{group.body}}
a suite of UI Components for development of web apps
Advanced User Interface Controls and Components
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.body}}
In our demo, when accordion header is right-clicked, a menu will appear with several options.
Similar: Add Groups to Angular 2 Accordion using Context Menu
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.
We can add or remove accordion groups using the context menu options. In our example the following operations are available:
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.
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.
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.