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()

m59
  • 43,214
  • 14
  • 119
  • 136
zerzer
  • 613
  • 2
  • 8
  • 20
  • Are you sure `$0` is working?. I don't know what you're doing with that... – m59 Jan 15 '14 at 01: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. – m59 Jan 15 '14 at 02:00
  • @m59 i've just executed `angular.element($0).scope()` in chrome console just to see what's happening in my scope [link](http://stackoverflow.com/questions/13743058/how-to-access-the-angular-scope-variable-in-browsers-console) but i get 'undefined' – zerzer Jan 15 '14 at 02: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. – m59 Jan 15 '14 at 02:05
  • By the way, disregarding the `angular.element`, you have a global function for a controller (bad practice), you're making an ajax call in the controller (should be in a service) and DOM manipulation in the controller with `.html()` (should be in a directive). It's ok if this is just a test, but you might want to study up on those things for production code. – m59 Jan 15 '14 at 02:07
  • @m59 i've been testing a lot of things when i put a string in scope like `$scope.foo = "test" ;` `{{test}}` work just fine but with a JSON object : `$scope.newMsgs = {'message':'hello'};` `{{newMsgs.message}}` doesn't work – zerzer Jan 15 '14 at 02:46
  • 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. – m59 Jan 15 '14 at 02:50
  • @m59 yes yes i'm sorry {{foo}} is working sorry but json object isn't – zerzer Jan 15 '14 at 02:53
  • finally ! $http is the solution thanks a lot @m59 !! – zerzer Jan 15 '14 at 02:54

1 Answers1

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.

m59
  • 43,214
  • 14
  • 119
  • 136
  • 1
    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 Jan 15 '14 at 04:41
  • @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. – m59 Jan 15 '14 at 04:53
  • 1
    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. – Norguard Jan 15 '14 at 05:07