0

For a specific dropdown menu I'd like to show different options based on booleans in my app. I've set everyhting up and things SORTA work, but the DOM isn't updating correctly to show the values in the dropdown. The console.logs I use to check the code output the corrects values for my variables, and when I refresh the page, the dropdown is filled just fine.

$scope.login = function () {
    var loginUrl = url;

    $server.post(loginUrl, $scope.user)
        .then(function(response) {
            var data = response.data;

            if(data.status == 'OK') {
                //some things here that work fine
                $scope.getRights();
            } else {
                $scope.user.password = '';
            }
        }
};

$scope.getRights = function() {
    console.log("yo");
    $scope.boolA = false;
    $scope.boolB = false;
    $scope.boolC = false;
    $scope.boolD = false;

    $scope.permissions.forEach(function (right) {
        console.log(right);
        switch(right) {
            case "A":
                $scope.boolA = true;
                break;
            case "B":
                $scope.boolB = true;
                break;
            case "C":
                $scope.boolC = true;
                break;
            case "D":
                $scope.boolD = true;
                break;
        }
    });
    console.log($scope.boolA + " " + $scope.boolB + " " + $scope.boolC + " " + $scope.boolD);
};

With matching html, correct controller is defined in an above lying <div>.

<ul class="dropdown-menu" uib-dropdown-menu role="menu">
    <li role="menuitem" ng-show="boolA"><a href="#/start">
        Option A
    </a></li>
    <li role="menuitem" ng-show="boolB"><a href>
        Option B
    </a></li>
    <li role="menuitem" ng-show="boolC"><a href>
        Option C
    </a></li>
    <li role="menuitem" ng-show="boolD"><a href>
        Option D
    </a></li>
</ul>

The json in $scope.permissions is ["A","B","D"]

My console.log outputs: true true false true

If I check the $scope variables in the browser, they're not set, and the dropdown options all have ng-hide active. When I refresh the page, they show up in the $scope inspector, and my dropdown has the correct values. So it looks like there's either a synch/asynch problem, or I'm using the incorrect route to set these variables.

Simply making them global doesn't change anything. A "simple" fix would be to force a reload after successfully loggin in, but this does not feel like "the angular way". I'm quite sure I'm just making a beginners mistake here. Can anyone help me in identifying where this mistake lies?

Kablam
  • 2,494
  • 5
  • 26
  • 47
  • 1
    I thought it might have been the issue of scope inheritance. You could debug your scope tree with https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en or https://chrome.google.com/webstore/detail/ng-inspector-for-angularj/aadgmnobpdmgmigaicncghmmoeflnamj and make sure the same objects are holding the values. – EmptyCup Dec 01 '16 at 16:41
  • Could be... when I log in with a clean cache, all the booleans are nonexistant - or set to false when I define them globally - and stay that way. Only after I actually refresh the page, they change to their proper values. That's not due to scope inheritance, is it? I define and set them in the same controller... – Kablam Dec 02 '16 at 09:57
  • Have you tried isolating this issue? Maybe try to reproduce it in a plunkr of your own while using the same setup (making a post request and filling in the boolX properties after it)? – Filipe Silva Dec 02 '16 at 11:36
  • @kablam Nope, If it was a issue with inheritance, it would create new objects. How does your scope tree look? Di you get a chance to use the chrome extensions? – EmptyCup Dec 05 '16 at 05:58
  • @FilipeSilva: I'll try that, thanks. – Kablam Dec 05 '16 at 10:02
  • @EmptyCup: Yes, I installed ng-inspector. I'm not sure what you mean by scope tree though, because I have rootScope, then as its first child loginController with the booleans, so that looks correct. When I login and keep looking at the ng-inspector pane, the variables just aren't getting set. But after a refresh, they're correct. – Kablam Dec 05 '16 at 10:07

1 Answers1

0

Instead of doing that can you not simply convert your "permissions" array into the menu item's list? That way the users won't be able to see the options in the html.

$scope.getRights = function() {
$scope.permissions = ["A", "B", "D"];
$scope.menuItems = [];
$scope.permissions.forEach(function(val) {
  $scope.menuItems.push({
    title: val
  });
});

}

<ul role="menu">
<li role="menuitem" ng-repeat="item in menuItems">
  <a>Option {{item.title}}</a>
</li>

Check this plunkr

Update

In this case your DOM is most likely not being updated because of an issue related to this post which suggests using $apply():

$scope.$apply(function(){
        $scope.boolA = false;
    });

Also, make sure you take a look on Danny Bullis comment:

Use $q.defer(); the object returned allows you to call a .resolve() or .reject() method once your async method is completed. Both resolve and reject methods of the $q.defer() object call $digest internally after the async method is resolved. The $digest tells angular to re-evaluate your $scope properties, which will do what you're looking for. It's a better practice. Avoid calling $apply() if you don't need to and if there are better, built-in angular mechanisms in place to take care of this.

Community
  • 1
  • 1
Filipe Silva
  • 220
  • 4
  • 10
  • This is an interesting point... worth looking into. Except what I'd like is to be able to refer to the different permissions on onther pages as well, for example to disable parts of a form. So even though I can use this way to hide options completely, I would still want to have booleans defined for later use. – Kablam Dec 01 '16 at 16:17
  • After your update: When I try to use $apply() or $digest() I get an error saying `$apply already in progress`. When I use $timeout (which also returns a promise as I found out) I get the console.log check after the page loads and the timeout ends, but still no values in my booleans. When I refresh the page, as soon as the timeout is done the variables are set and the menu filled. It has to be something else.... – Kablam Dec 02 '16 at 10:23