1

We are building a big SPA , currently the app is build with widgets/components. each with a template, controller. but many can be nested in the same route. for example: In the route /users/ I can have a `userCtrl and a userTemplatethat renders the user stats parts. a graphCtrl and a graphTemplate to render some d3 graphs. a listCtrl and a listTemplate to render a list. all of those widgets should be reusable (with different css and layouts, sometimes with the same ctrl different templates in other pages). I need to instantiate some data from a service - Lets say a service that return my user id and more validations. so in the main app routing i define a resolve{myId: function(srvname){return srvname.myId}} for userCtrl route which the when clause of routeProvider routes to.

My problem is that listCtrl doesn't wait for userCtrl (the main page ctrl , which gets the route) to resolve the different promises, and then fails with missing data.

Is there a way to define the same resolve for multiple controllers, that some of them aren't a direct route target but more of (very) big component? Is there a better/smarter way to do this?

I know I can use directive for that. but moving the bussiness logic from listCtrl to a directive looks plain wrong.

I'll be glad for any help and advice

1 Answer 1

1

The standard advice for communicating between controllers is to use a service. If I'm reading your description right, then in your case the top-level controller would be responsible for setting up the model and setting it in the service for the "descendant" controllers to read.

Edit for @alonisser's comment:

You should be able to data-bind the dependent controller's view to a function on the dependent $scope (say viewData() in such a way that if the function returns null, the element is hidden or shows a "spinner" UI.

The dependent template would look something like:

...
<div data-ng-if="viewData() !== null">
    <!-- show display elements based on the return value from viewData() -->
</div>
...

The setup for viewData would look something like this:

...
$scope.viewData = function() {
    if ($scope.model.asyncData === null) {
        $log.info("no data yet!");
        return null;
    }
    else
        return prepare_for_view($scope.model.asyncData);
}
...

And the async calls in the userCtrl look something like:

something_that_returns_a_promise.then(function (result) {
    $scope.model.asyncData = result;
});

A key piece is that the something_that_returns_a_promise() has to be something "inside" the AngularJS call stack, for example done using $http. When that's the case, Angular automatically calls $scope.$apply(), and your dependent display elements should update seamlessly. Otherwise you will need to call $scope.$apply() yourself in the async callback that sets $scope.model.asyncData.

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

1 Comment

thanks @david-pope but I think you are missing the point here, the top level controller does set the model. but since the async operations involved the other controllers don't wait for it and just fail. ''' resolving''' would do the trick, but the controllers just run without waiting for the top-level controller to resolve. I s there a way to force them to?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.