prawn
prawn

Reputation: 2653

Showing and hiding menu items efficiently

Right now I have a navigation menu. However, depending on your job title you can only see certain menu items.

The html I have looks like the following

<ul>
      <li ng-repeat="item in navigationItems | orderBy:'-ID'">
           <a href="#/{{item.Name}}">{{item.Name}}</a>
      </li>
</ul>

and the controller for this is as follows...

$scope.navigationItems =
        [
            {
                Name: "Item 1",
                ID: 1
            },
            {
                Name: "Item 2",
                ID: 2
            },
            {
                Name: "Item 3",
                ID: 3
            },
            {
                Name: "Item 4",
                ID: 4
            },                           
        ]

This has been simplified. In reality there are 15 menu items.

There are five different job titles, and for each job title, they can only see certain menu items. How can I avoid doing a check for each title followed by the menu items they can see...for example this is what I do not want to do....

if(JobTitle=="Manager")
{
      $scope.navigationItems = [item 1, item 2, item 12, item 7....]
}
else if(JobTitle =="Staff")
{
      $scope.navigationItems = [item 5, item 9, item 12, item 15....]
}
else if(JobTitle == "Whatever")
{
      $scope.navigationItems = [item 12, item 14, item 15....]
}

and so on. Is there a better, more optimal way to go about doing this in angular instead of having to retype some of the menu items for each case?

Upvotes: 0

Views: 88

Answers (2)

gkalpak
gkalpak

Reputation: 48211

What is the best approach depends on your criteria and other requirements, but one possible (and possibly "good") approach is to extend each navigation item with an array of "allowed" job-titles (Roles) and then create (and use) a custom filter that filters the navigation items by job-title (role).

Important note:
As others have mentioned, it is very important to understand that this is for UI and presentation purposes only and no security is provided by just hiding away View elements. Any role-based restrictions should be enforced on the server-side.


<ul>
    <li ng-repeat="item in navigationItems | filterByRole:jobTitle | orderBy:-'ID'">
        <a href="#/{{item.Name}}">{{item.Name}}</a>
    </li>
</ul>

$scope.navigationItems = [{
    Name: "Item 1",
    ID: 1,
    Roles: [...]
}, {
    Name: "Item 2",
    ID: 2,
    Roles: [...]
}, {
   ...

app.filter('filterByRole', function () {
    return function (items, role) {
        return items.filter(function (item) {
            return item.Roles.indexOf(role) !== -1;
        });
    };
});

See, also, this short demo.

Upvotes: 2

kpentchev
kpentchev

Reputation: 3090

You could put the menu items in a Map structure, with the keys being the JobTitles and the values the array of menu items. The Whatever case can be handled as a default array if key is not present in the Map, i.e undefined.

var jobTitleToMenuItems = {}
jobTitleToMenuItems["Manager"] = [item 1, item 2, item 12, item 7....];
jobTitleToMenuItems["Staff"] = [item 5, item 9, item 12, item 15....];
var defaultMenuItems = [item 12, item 14, item 15....];

var menuItems = jobTitleToMenuItems[JobTitle];
$scope.navigationItems = menuItems ? menuItems : defaultMenuItems;

Alternatively, if it makes sense with other design issues (e.g. another property specific for the JobTitle) define objects of type Job, with properties title (String) and navigation_items (array).

Upvotes: 0

Related Questions