0

Here's my setup -- I have a controller that is using a service that does some work and then returns data asynchronously. In this case, the data is returned by a timeout, but in real life this would do something more interesting:

View:

<div ng-controller="RootController as root">

  <h1>Angular Project</h1>
  <div ng-show="{{root.greeting}}">
    <p>{{root.greeting}}</p>
  </div>

</div>

Controller:

(function(){

  'use strict';

  function RootController(greetingService) {

    var vm = this;
    vm.greeting = '';

    // startup logic
    activate();

    function activate() {
        greetingService.greeting().then(
          function( response ) {
              vm.greeting = response;
          },
          function( error ) {
              vm.greeting = error;
          }
        );
    }
  }
  RootController.$inject = ['greeting'];
  angular.module('app.core').controller('RootController', RootController);

})();

Service:

(function() {
  'use strict';

  // Greeting Service
  function greeting( $timeout ) {

    // public API
    var service = {
        greeting:   greeting
    };
    return service;

    // internal functions
    function greeting() {
        return $timeout( function() {
            return 'Hello world!'; 
        }, 1000 );
    }

  }

  temp.$inject = ['$timeout'];
  angular.module('app.core').factory( 'greeting', greeting );

})();

Questions:

  1. Why is it that my view is not updating when the timeout resolves and the vm.greeting assignment occurs in my controller? I've seen people describe "inside Angular vs outside Angular", but it would seem to me that I haven't gone "outside Angular" here.

  2. I'm aware that I can call $scope.$apply(), but I've encountered the "digest is already in progress" error, and again it doesn't seem like I should have to do this.

  3. Is there a better way I should be organizing my components? I have also experimented with broadcasting an event over $rootScope and writing an event handler in the Controller, but this arrangement exhibits the same outcome (namely the view is not updated when the asynchronous model change occurs).

Community
  • 1
  • 1
Alex
  • 855
  • 7
  • 21
  • is it actually making it to the .success? Can you verify vm.greeting is actually being set? – ribsies Feb 23 '15 at 23:10
  • @ribsies yes. I edited the code for this question to get rid of everything extraneous, but the timeout is resolving and my .then( success) function is executing. When I debug the scope in Chrome Dev Tools and look at the value of angular.element($0).scope().root.greeting, I see the correct value. – Alex Feb 23 '15 at 23:16

2 Answers2

1

You don't need the curly braces for ng-show

https://docs.angularjs.org/api/ng/directive/ngShow

change

<div ng-show="{{root.greeting}}">

to

<div ng-show="root.greeting">
goreorto
  • 302
  • 2
  • 9
0

The way you have structured your code is a very different from what I normally do. Check out this link for a great style guide.http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/

As for your issue, Angular uses $scope to bind a value in the controller to the view. So your controller should have $scope injected and you can then do$scope.greeting in place of vm.greeting.

Davie
  • 818
  • 3
  • 12
  • 24
  • The use (or lack of use) of $scope was not my problem. Using the "controller as..." syntax means you don't assign your properties and functions onto $scope but onto your Controller object instead. – Alex Feb 23 '15 at 23:55
  • Like I said I do things differently but I will leave my answer as the style guide is worth a read in my opinion. – Davie Feb 23 '15 at 23:57
  • Will take a look at that link you refer to. I've taken a look at a lot of examples but liking this guidance so far: https://github.com/johnpapa/angularjs-styleguide – Alex Feb 24 '15 at 01:36