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

2
  • is it actually making it to the .success? Can you verify vm.greeting is actually being set? Commented Feb 23, 2015 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. Commented Feb 23, 2015 at 23:16

2 Answers 2

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">
Sign up to request clarification or add additional context in comments.

Comments

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.

3 Comments

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.
Like I said I do things differently but I will leave my answer as the style guide is worth a read in my opinion.
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: github.com/johnpapa/angularjs-styleguide

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.