2

Here is my route config

 $stateProvider.state('layout', {
            abstract: true,
            controller: "MenuCtrl",
            templateUrl: "views/layout/MainLayout.html"
        }).
            state('layout.home', {
                url: '/',
                templateUrl: 'views/Main.html',
                controller: 'MainCtrl'
            }).state('layout.tag.add', {
                url: '/addTag',
                templateUrl: 'views/AddTag.html',
                controller: 'AddTagCtrl'
            })

Later I have in my code function:

 var goToAddTagPage = function(){
        $state.go('layout.tag.add');
    };

When I call this function I get Could not resolve 'layout.tag.add' from state 'layout'. If I rename this to layout.addTag it works correctly. Nested tag causes issue. How I can correctly nest states like that? EDIT: I have added empty state

state('layout.tag',{

}).

Now exception is gone. However the view is now not rendered. I get empty screen. I try to add abstract : true for state but it didn't helped.This state need some configuration?

2 Answers 2

2

In your state hierarchy, there really must be all three states.

state('layout', {...}
state('layout.tag', {...}
state('layout.tag.add', {...}

Because a '.' (dot) in the state name simply represents hierarchy (parents, grand parents)

But once we add new parent between grand-parent and child, we need to be sure, that

  • parent contains a view "target" for a child.
  • child explicitly uses absolute view naming to target grand-parent

So, this would work (and I would prefer that, because we gain inheritance parent-child)

state('layout.tag', {
    template: '<div ui-view ></div>'
    ...
}

So now, there is the element <div ui-view ></div> injected into grand-parent, and also serves as an anchor/target for child.

Check the doc:

Scope Inheritance by View Hierarchy Only

Keep in mind that scope properties only inherit down the state chain if the views of your states are nested. Inheritance of scope properties has nothing to do with the nesting of your states and everything to do with the nesting of your views (templates).

It is entirely possible that you have nested states whose templates populate ui-views at various non-nested locations within your site. In this scenario you cannot expect to access the scope variables of parent state views within the views of children states.

The second approach is to use absolute view naming and skip grand parent

.state('layout.tag.add', {
    url: '/addTag',
    views: {
      '@layout': { // target unnamed view anchor in grand-parent
         templateUrl: 'views/AddTag.html',
         controller: 'AddTagCtrl'
         }
     }
 })

View Names - Relative vs. Absolute Names

Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname@statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.

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

1 Comment

Great if that helped anyhow, Enjoy ui-router :)
1

You may(dont quote me on this, but try) need to introduce an intermediate layout.tag state if you want to use this hierarchy.

UI router could be failing on 'dot-notation' based nesting because youre skipping a state essentially.

Update: Based on the regex in this snippet from the source

var compositeName = /^(.+)\.[^.]+$/.exec(state.name);

It does look for a parent state named 'layout.tag'.

So you will either need to accept the 'layout.addTag' hierarchy or introduce an intermediate 'layout.tag' state

Comments

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.