1
votes

I am using Angular UI-Router and need to have a single parent state that several other states can inherit the results of a resolve from. I have tried every solution found here on SO for this but NOTHING is working. My states look like this:

.state('transaction', {
    abstract:true,
    url: '/register/pos/:screen/:document_sid',
    template:'<div ui-view></div>',
    resolve: {
        Document: //the thing I need to have all the children access
    }
})
.state('transaction.view', {
    url:'',
    views:{
        '':{
            templateUrl: '/views/docs/pos-transaction-outer-partial.htm',
            controller:'posdocumentController'
        }
    }
})
.state('transaction.edit', {
    url: '/:mode',
    views:{
        '':{
            templateUrl: '/views/docs/pos-transaction-outer-partial.htm',
            controller:'posdocumentController'
        }
    }
})
.state('transaction.returns', {
    url: '/returns',
    views:{
        '':{
            templateUrl: '/views/pos-itemreturn-partial.htm',
            controller: 'posItemReturnsController'
        }
    }
})

When I use $state.go('transaction.edit') it works perfectly. Inside the 'posdocumentController' I have a function that calls $state.go('transaction.returns') and I can see the route change and the partial is requested, but the view never changes. According to the docs for multiple named views the specified views should load in the parents ui-view that is contained within the template. Obviously, for me this is not happening and for the life of me I have not been able to figure out why. I've tried this both with and without the views option and get the same results. Can someone explain why and how I fix this?

1

1 Answers

0
votes

In details is hidden... in very small detail, in this case.

I. Why not working?

Here is a plunker with broken navigation (exactly as described in the question above)

These would be the calls to the above states:

ui-sref
transaction.view ({ screen: 1 ,document_sid:2 ,mode:5 })
transaction.edit ({ screen: 1 ,document_sid:2 ,mode:5 })
transaction.returns ({ screen: 1 ,document_sid:2 ,mode:5 })

href
#/register/pos/1/2
#/register/pos/1/2/5
#/register/pos/1/2/returns

so, while these could seem as proper state calls, the last two, edit and returns, could be observed as:

// edit link result
params
{
  "screen": "1",
  "document_sid": "2",
  "mode": 5
}
state
{
  "url": "/:mode",
  ...

// returns link result
params
{
  "screen": "1",
  "document_sid": "2",
  "mode": "returns"
}
state
{
  "url": "/:mode",

Now it should be clear. The third link (to state returns) is in fact navigating to edit again. Why? because of this states definition:

.state('transaction.edit', {
    url: '/:mode',     // here we say :mode is param
    ...
.state('transaction.returns', {
    url: '/returns',   // and 'returns' here is already mapped... above as :mode

Check the not working solution here

II. How to make it working

There is a link to working plunker. The change made is:

firstly define returns and then edit state

.state('transaction.returns', {
    url: '/returns',   // 'returns' would be evaulated first, and used
    ...
.state('transaction.edit', {
    url: '/:mode',     // only other then returns values will be used here

Working solution is here

Other solution, maybe better, would be to use some regex... to narrow :mode values: Regex Parameters

  • '/user/{id:[^/]*}' - Same as '/user/{id}' from the previous example.
  • '/user/{id:[0-9a-fA-F]{1,8}}' - Similar to the previous example, but only matches if the id parameter consists of 1 to 8 hex digits.
  • '/files/{path:.*}' - Matches any URL starting with '/files/' and captures the rest of the path into the parameter 'path'.
  • '/files/*path' - Ditto. Special syntax for catch all.