Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them, it only takes a minute:

I'm making a document editor. Documents can be Type A or Type B. They are accessed by url by document id, but the id does not make it clear if the document is of type A or B.

So, I need to load the document by id, determine its type from its data, and then pass it to either the TypeAController or TypeBController.

Right now, with ui-router, I have something like this:

$stateProvider
.state('loading', {
    url: '/{documentId}',
    template: 'Loading...',
    controller: function ($stateParams, $state) {
        loadDocument($stateParams.documentId)
            .then(function (loadedDocument) {
                if (loadedDocument.type === 'A') {
                    $state.go('EditA');
                } else if (loadedDocument.type === 'B') {
                    $state.go('EditB');
                }
            })
    }
})
.state('A', {...})
.state('B', {...})

The loading state loads the document, determines its type, and then goes to the next state.

Frustratingly, though, I can't find a way to actually pass the loaded document to the next states! I can make a globalish service into which I can insert the document, or I can just pass the id of the document along and load it again in each state (hopefully from a cache this time), but these methods are so clunky and everything else about angular and angular-ui has been so smooth.

Any suggestions?

share|improve this question

2 Answers 2

up vote 11 down vote accepted

One solution could be to move it to the parent state, which is available to all children. Something like this:

$stateProvider
.state('loading', {
    url: '/{documentId}',
    template: 'Loading...',
    controller: function ($scope, $stateParams, $state) {
        loadDocument($stateParams.documentId)
            .then(function (loadedDocument) {

                // assign the document to the parent model $scope
                // in this case $scope.model.doc  
                $scope.model = { "doc" : loadedDocument };
                if (loadedDocument.type === 'A') {
                    $state.go('.EditA');
                } else if (loadedDocument.type === 'B') {
                    $state.go('.EditB');
                }
            })
    }
})
.state('loading.EditA', {...}) // here we can use the $scope.model.doc
.state('loading.EditB', {...}) // in every child state

The $scope.model.doc represents the reference to the shared document.

Here (UI-Router example - contact.js) we can see how parent is setting the contacts collection, all child states are accessing it. The example in action

share|improve this answer
    
This looks great - it also looks like the resolve hash of a parent state can be used to inject dependencies to children states on the fly when you don't want to add things to $scope. Thanks! – Riley Lark Nov 17 '13 at 15:03
    
This $scope technique only works if the states have nested views, otherwise you'll need to use $rootScope. – Oran Dennison May 20 '14 at 0:43
    
ui-router-example link is broken... – Vishwanath Oct 16 '14 at 8:01
    
@Vishwanath, thanks sir. The link is fixed... – Radim Köhler Oct 16 '14 at 8:07

You could have a Documents service which owns and provides an API to all the document data. The controllers then inject the Documents service, and reference the document they're interested in on their scope.

Something like:

app.service('Documents', function(){
  Documents = {};

  return {
    open: function(doc_id) { ... }  // loads and caches doc (if not already cached) and returns a promise with a reference to Documents[doc_id]
    sync: function(doc_id) { ... }  // sync doc with server
    close: function(doc_id) { ... } // remove doc_id from Documents 
  };
});

app.controller('editX', function($scope, $stateParams, Documents){
  Documents.open($stateParams.documentId).then(function(ref){
    $scope.document = ref;
  });

  ...

})
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.