0

I use several javascript global constants to communicate state across controllers on my page. Maybe that's a bad idea, but it works for me to cut down on typing errors and centralizes the place where I invent these names to one place in my code.

Different parts of my page in different controllers are meant to display or be hidden depending on these global states. So I have one state which is defined

const DISPLAY_STATE_CHART ="showChart";

and the parent scope of several interested controllers can query a map maintained by this parent scope. The map can be queried by a key which, based on these state constants, sort of like:

 state = $scope.$parent.displayStateMap.get(DISPLAY_STATE_CHART);

state is a boolean which is used to determine whether a div should be displayed or not.

So on my page, I want to display a div if the 'state' is true, I include an ng-if:

<div ng-if="getDisplayState(DISPLAY_STATE_CHART)">some content</div>

In my controller I have a function defined like:

$scope.getDisplayState(when_display_state) {
    return $scope.$parent.displayStateMap(when_display_state);
 }

However the constant name encoded in the HTML is not getting through somehow, and when_display_state is coming through as "undefined".

If I change the html to use the string value, e.g.

 <div ng-if="getDisplayState('showChart')">some content</div>

it works as expected, so it seems clear that the problem is that whatever part of Angular is interpreting the html string attached to ng-if is somehow unaware of these global constants.

Is there a solution to this?

Thanks.

1

You cannot use variables defined with const inside an ng-if. Inside an ng-if you can only use variables which are defined in the $scope of the particular template.

Refer to this SO answer, which is a response to an issue similar to yours.

But I can suggest you a workaround if you don't like moving the value of the particular const value into a scope variable, in case you don't mind setting your DOM elements via javascript.

Modify this line: <div ng-if="getDisplayState(DISPLAY_STATE_CHART)">some content</div> as follows: <div id="displayState"></div>.

And inside your javascript, run a function onload of the browser window which would check for the DISPLAY_STATE_CHART using the $scope.getDisplayState() function. Just the way you would display the div content based on its value, just set div value inside the javascript itself when the condition is satisfied, something like:

  function run() {
    if ($scope.getDisplayState(DISPLAY_STATE_CHART)) {
      document.getElementById("displayState").innerHTML ="some content";
    }
  }
  window.onload = function() {
      run();
  }

I've created a runnable script(just with sample values). Just for some better understanding.

var app = angular.module('constApp', []);
app.controller('constCtrl', function($scope) {

  const DISPLAY_STATE_CHART = true;

  $scope.getDisplayState = function(dsc) {
    return dsc;
  }

  function run() {
    if ($scope.getDisplayState(DISPLAY_STATE_CHART)) {
      document.getElementById("displayState").innerHTML ="some content";
    }
  }
  window.onload = function() {
      run();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="constApp" ng-controller="constCtrl">
  <div id="displayState"></div>
</div>

  • 1
    Thank you Rai. I guess I will have to move the vars into the controller scope rather than the global namespace. onload doesn't really work in my case because the page state changes by Ajax sometimes. doesn't always follow a reload. – user1023110 Mar 12 at 16:48
  • Moving the vars into the controller is good for another reason as well, namely, it isn't that good a practice to use global variables because of the unwanted exposure the variables are subjected to, as stated in this article. Also, since you have told about Ajax changing the state of the page, this SO post may help you. – Rai Mar 13 at 5:53
  • The article you quote is talking about global variables not global constants which mitigate the risk of unwanted exposure given they are not ‘secrets’. Having to move the definitions into a number of different controllers creases it’s own set of problems not worth going into I guess given that it’s actually impossible anyway. – user1023110 Mar 13 at 7:42

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.