12

i have this code and i can't see where is the source of problem, i don't get any error in the chrome console my controller :

function notifController($scope) {
  $scope.refreshMsgs = function () {
    $.post("notification-center-trait.aspx")
      .success(function (data) {
        $("#loadedthings").html(data);
        newMsgs = JSON.parse($("#label1").html());
        $scope.msgs = newMsgs;
      });
  }
  $scope.refreshMsgs();
}

label1 and label2 are loaded correctly inside a div loadedthings;

newMsgs in the console is parsed just the way it should;

i had it working for other pages but it seems that i missed something on this one.i have <html ng-app> tag :

<div ng-controller="notifController"> 
    <div class="row">
    {{msgs.length}} new msgs : 
              <table class="table">
                  <tbody >
                      <tr ng-repeat="msg in msgs">
                        <td>
                            {{msg.sender}}
                        </td>
                        <td>
                            {{msg.message}}
                        </td>
                        <td>
                            {{msg.date}}
                        </td>
                      </tr>
                  </tbody>
              </table>
</div>
</div>

i get 'undefined' in the console when i execute this : angular.element($0).scope()

9
  • Are you sure $0 is working?. I don't know what you're doing with that... Commented Jan 15, 2014 at 1:54
  • I tested your code and everything here is working fine. I suspect that you're messing with the DOM inappropriately and have made a mistake. Anything like angular.element belongs in a directive. Angular makes the scope property available wherever you need it, other than maybe rare exceptions, so you should not need to access an element or a scope this way. Commented Jan 15, 2014 at 2:00
  • @m59 i've just executed angular.element($0).scope() in chrome console just to see what's happening in my scope link but i get 'undefined' Commented Jan 15, 2014 at 2:01
  • As I said, with the code you have here, the controller is initialized and the data-binding is working. The problem you are having is not conveyed in this code. Just to be absolutely sure, do this: $scope.foo = 'test' and in your markup: {{foo}}. Perhaps your ajax call just isn't coming through? If the controller truly isn't working, something else (not in this code) is the issue. Commented Jan 15, 2014 at 2:05
  • 1
    What you just described isn't even valid.... that would have to be {{foo}}. You definitely have a simple error that you could debug with the console, I'm certain. Also, Angular has the $http for ajax calls, you should be using that rather than jQuery. Commented Jan 15, 2014 at 2:50

1 Answer 1

25

Disregarding other architectural issues I pointed out in the comments, the real issue is that you're using jQuery's ajax instead of Angular's $http. When you don't do things like that through Angular, you're working outside of Angular's scope and it doesn't know about changes. While not ideal, you can use $scope.$apply to let angular know something was updated outside of its knowledge. That would look like this:

$scope.$apply(function() {
  $scope.msgs = newMsgs;
});

That is telling Angular that you've modified something it needs to know about from a context that it doesn't know about (the jQuery ajax call in this case).

There are some valid uses of $scope.$apply(), such as in event handlers, but most other times it is a sign of bad practices. You should definitely be using Angular's $http for ajax calls.

Sign up to request clarification or add additional context in comments.

3 Comments

As an addendum, $scope.$apply can throw errors if you use it at the wrong time (you can't just put it everywhere you're misbehaving, as a solution to them all), however, $timeout (an Angular wrapper for setTimeout) will behave all the time, and make sure that your changes end up in the next $apply pass (which is where they would have landed anyway). It shouldn't be abused, but it's safer than $apply, without dirty hacks in directives, to check if it's safe/needed or not.
@Norguard True...but if you are ever using $apply in a place that it throws an error, it shouldn't be used at all. That's a huge code smell. Like I said, $apply is usually not needed at all unless you're using events or third-party libraries.
absolutely. But some of those third-party libraries are half-sync, half-async, and others go down their own rabbit-holes of pub/sub or setTimeout, or just require you to dance around them in those circles, yourself. I know first-hand that if you're not careful, both MasonryJS (for pinterest/infinite-tumble layouts) and D3JS (for making tweenable SVG graphs) can both provide their share of misery with if (!$scope.$rootScope.$$phase) nonsense, if Angular is only partially tied into the process (like calling Msnry.stamp + Msnry.layout on an ng-repeat ...). $timeout is then very elegant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.