-2

I'm building a dashboard similar to this one Admin Dashboard Theme

I'm implementing the Right Side SideBar as show in the screenshot enter image description here

My App code structure is something like:

index.html:
<div ui-view=""></div> 

main.html
<div ui-view=""></div> 
<div ng-include='"app/dashboard/sidebar.html"'></div> 

I have done nesting of view in my main.html where I'm injecting different views. Also, since my right side sidebar is fixed, I want it to be common in all the main views. So, I have just included it in my main.html.

Now, the problem is somehow my sidebar.html is getting initialized again and again no matter if I scroll my page down or perform any action inside sidebar. I have verified it by printing console logs for every controller function which are used in sidebar.html view.

This problem is related to my this post: Earlier, I wasn't able to figure out the actual issue.

Following is my controller and jade code:

angular.module('myApp')
  .controller('SidebarCtrl', function($scope, $rootScope) {
    $scope.message = {};

    $scope.addSideBarToggleClass = function() {
      console.log("addSideBarToggleClass");
      return true;
    }

    $scope.getStatusClass = function(status) {
      console.log("getStatusClass");
      return 'is-online';
    }

    $scope.openChat = function(receiver) {
      console.log("openChat");
    }

    // etc...

  });
<aside ng-class="{ 'control-sidebar-open' : addSideBarToggleClass()}" 
       ng-controller="SidebarCtrl">
  <ul>
    <li ng-class="{active: isTabSelected('chat')}">
      <a data-toggle="tab" ng-click="updateCurrenTab('chat')"></a>
    </li>
    <li ng-class="{active: isTabSelected('home')}">
      <a data-toggle="tab" ng-click="updateCurrenTab('home')"></a>
    </li>
  </ul>
  <div>
    <div ng-class="{active: isTabSelected('home')}">
      <h3>Recent Activity</h3>
    </div>
    <div ng-class="{active: isTabSelected('chat')}">
      <div>
        <h4>Chat {{noOfUsersOnline}}</h4>
        <div>Friends
          <a href="#" ng-repeat="user in users" ng-click="openChat(user)"> 
           <span ng-class="getStatusClass(user.status)"></span>
           {{user.name}}</a>
        </div>
      </div>
    </div>
  </div>
</aside>

I see many logs of "addSideBarToggleClass", "getStatusClass" and every time I click on openChat, I see a log of "openChat" and then again "addSideBarToggleClass" and "getStatusClass"

Can anyone please point out what can be the possible problem for this behavior?

Community
  • 1
  • 1
dark_shadow
  • 3,503
  • 11
  • 56
  • 81
  • 3
    Too much code to wade through. Pare it down to get rid of everything that does not matter, which appears to be most of it. People will be more quick to try to figure out the answer if they don't have to read so much to even pinpoint where the problem is. – Seth Flowers Jul 30 '15 at 19:21
  • @sethflowers: ok...I'm removing the code which I think shouldn't be an issue. – dark_shadow Jul 30 '15 at 19:23
  • @sethflowers: I have updated the code. Let me know if there is still something which needs to be done – dark_shadow Jul 30 '15 at 19:29
  • 1
    @dark_shadow, still *waaay* too much. You should be able to reduce the problem on your own. Do we need all the styling markup? Do we need all this app-specific functionality? Do we need *any* functionality other than having a `console.log` in the view? – New Dev Jul 31 '15 at 03:05
  • @NewDev: I have re-iterated the code as as to reduce it. Please take a look at it and let me know if it still needs more refinement ? – dark_shadow Jul 31 '15 at 03:33
  • @NewDev: I have left few functionality in controller like toggling of tab and a list of online users and their corresponding ng-click functions. I think if you want to simplify the case you can take an example where you have only two tabs with some content and some console.log function in controller which are printed on page scroll of main.html or even if you click online users and open a chat box. Try writing any text in the box, it will again print all console.log messages – dark_shadow Jul 31 '15 at 03:36
  • Which `console.log` is getting called repeatedly? Is it `console.log($rootScope.isSideBarToggled.val);` and `console.log(status);`? – New Dev Jul 31 '15 at 04:31
  • console.log(status); console.log($scope.receiverId); if you click on open chat are getting called again – dark_shadow Jul 31 '15 at 06:57
  • Also, there are other logs which are getting called again even if you are typing text in chat box. Since I have removed a large fraction of code of my controller, I can't show them over here exactly which logs. But the issue is somehow angular is creating the view again and thus going through the controller again so that all the functions which are required for populating conditional classes or some other variables in the view, are getting called again – dark_shadow Jul 31 '15 at 06:58
  • @dark_shadow, I answered below. Also, for future reference, I will edit your question to reduce the code you posted to showcase what we meant by "reduce" – New Dev Jul 31 '15 at 13:22

1 Answers1

1

You need to familiarize yourself with the concept of a digest loop in Angular.

In short, every time a digest loop runs, all expressions, e.g. {{name}} or ng-show="isActive && isEnabled", that are being "$watched" by Angular are evaluated (sometimes more than once). This means that if you are invoking a function inside an expression:

<div ng-show="isShown()">
$scope.isShown = function(){
   console.log("expect to see this text a lot of times");
   return true;
};

the function will be executed on every digest loop.

A digest loop runs any time that something in Angular calls $scope.$digest, which by default happens on things like ng-click or ng-change or $http.then, etc..

New Dev
  • 48,427
  • 12
  • 87
  • 129
  • First of all, thank you very much. You showed me exactly how to post only relevant code for the problem. One quick question, as you mentioned that A digest loop happens on things like ng-click or ng-change, then this should be experienced in other views as well ? I have many views in my web app but this particular thing is noticed only in this nested view. Is it something happens only in nested views? Also, since my actual event like scrolling happens on the page, why is it changing the sidebar view again ? Are there any work around which I can do to fix this? – dark_shadow Jul 31 '15 at 14:45
  • @dark_shadow, maybe other views don't have $watched functions, e.g. `{{someFunction()}}`, like you do in this view, so you don't see that they are being called. I'm not sure I get your last question – New Dev Jul 31 '15 at 15:30
  • But is there anything which I can do to fix it ? What I mean by my last question is how do I suppress this behaviour ? Moreover, should I try to suppress this or this is expected behaviour of angularjs ? Also, if this expected behaviour should not this will result in performance degradation as everytime you are watching functions ? – dark_shadow Jul 31 '15 at 16:01
  • @dark_shadow, this is how Angular works - it does "dirty-checking" to track what $watched expressions have changed return values. The most significant factor of performance in Angular apps is the $digest cycle, which depends on the number of $watched expressions and the amount of time it takes to execute one. So, $watched function must be very fast - almost getters - and definitely not do any loops or async calls – New Dev Jul 31 '15 at 16:13
  • Thank you so much for the help. Now I got it. That's the reason why I'm not seeing any logs for ng-click() functions. I think $watched expressions doesn't include ng-click()/ng-submit() events. Please correct me if I'm wrong. Also, it will be great if you can point me to some good tips for increasing the performance of my angular app and how can I avoid the use of $watched expression. Also, can we increase the time in which $digest event happens? May be it can include some optimization ? – dark_shadow Jul 31 '15 at 18:38