Search code examples
javascriptjsonangularjsangularjs-directivemeanjs

With AngularJS, how can I leverage ng-show against an array to find certain values?


I have a model, Program, that looks something like this

var ProgramSchema = new Schema({
  permissions: [{
      user: {
        type: Schema.ObjectId,
        ref: 'User'
      },
      roles: {
        type: [{
            type: String,
            enum: ['reader', 'editor', 'admin', 'requested']
          }]
      }
    }],
  type: {
    type: String,
    enum: ['public', 'private'],
    default: 'public',
    required: 'Type cannot be blank'
  }
});

As display a list of programs on a page, I want to show an icon if the currently authenticated user $scope.authentication.user is in the program.permissions.user and with a role of reader, editor, or admin. I was thinking of an ng-show but since programs.permissions is an array, I couldn't make it work. Any help would be great! thanks!

sample program data

{
    "_id" : ObjectId("55ab4acd24640cd55097c356"),
    "permissions" : [ 
        {
            "user" : ObjectId("55a897dfad783baa677e1326"),
            "roles" : [ 
                "reader"
            ]
        }, 
        {
            "user" : ObjectId("5563f65a84426d913ae8334e"),
            "roles" : [ 
                "editor"
            ]
        }
    ]
}

Thru some help, here is what I ended up doing

I called a function in my ng-show

ng-show="userFollowedProgram(program)"

In my controller

$scope.userFollowedProgram = function(program) {
  //loop thru permissions and see if user is in there.
  for (var i = 0; i < program.permissions.length; i++) {
    if (program.permissions[i].user === $scope.authentication.user._id) {
      //loop thru roles and see if user is following.
      if (program.permissions[i].roles.indexOf('admin') > -1 ||
          program.permissions[i].roles.indexOf('editor') > -1 ||
          program.permissions[i].roles.indexOf('reader') > -1) {
          return true
        }
    }
  }
  return false;

};

Solution

  • While not be the prettiest, you can explicitly check for your values with the || logical operator on your ng-show using indexOf(). I've mocked a simple example, using a <span> as an "icon" - but you can certainly work the idea into your working copy from here. Observe the following...

    <li ng-repeat="user in users">
        <span>{{ user.name }}</span>
        <span class="ico" 
              ng-show="user.roles.indexOf('reader') > -1 || user.roles.indexOf('editor') > -1 || user.roles.indexOf('admin') >-1">icon
        </span>
    </li>
    

    $scope.users = [{
            id: 1, name: 'bob', roles: ['reader', 'editor', 'admin']
        },{
            id: 2, name: 'jane', roles: ['reader']
        },{
            id: 3, name: 'chris', roles: ['editor']
        },{
            id: 4, name: 'susy', roles: ['requested'] // sorry susy
    }];
    

    JSFiddle Link - simple demo


    Another interesting way you can accomplish could include testing for their role via regex and return a truthy value. Could be more overhead than it's worth, but check it out if you wish...

    <span class="ico" ng-show="isInRole(user)" >icon</span>
    

    $scope.isInRole = function(user) {
        return /(reader|editor|admin)/.test(user.roles.join('|'));
    }
    

    JSFiddle Link - regex demo