AncientSwordRage
AncientSwordRage

Reputation: 7608

With multiple views my child template is not loading, in Angular UI when URL changes

I've seen a few questions like this, so forgive me if I've overlooked a crucial detail from them.

When I load http://localhost:8000/characters/#/mages/detail/3 I get redirected to my 'otherwise' url: $urlRouterProvider.otherwise("/users");

But my state provider (if I've understood this correctly) should load the correct page:

  $stateProvider
    .state('users', {
      url: "/users",
      templateUrl: DjangoProperties.STATIC_URL + "partials/users.html"
    })
    .state('users.list', {
      url: "/list",
      templateUrl: DjangoProperties.STATIC_URL +  "partials/users.list.html",
      controller: 'UserListCtrl'
    })
    .state('users.detail', {
      url: "/detail/{userID:int}",
      templateUrl: DjangoProperties.STATIC_URL +  "partials/users.detail.html",
      controller: 'UserDetailCtrl'
    })
    .state('mages', {
      url: "/mages",
      templateUrl: DjangoProperties.STATIC_URL + "partials/mages.html"
    })
    .state('mages.list', {
      url: "/list",
      templateUrl: DjangoProperties.STATIC_URL + "partials/mages.list.html",
      controller: 'MageCtrl'
    })
    .state('mages.detail', {
         url: "/detail/{mageID:int}",
         views:{
            "@mage.detail": {
                templateUrl: DjangoProperties.STATIC_URL +  "partials/mages.detail.html",
                controller: 'MageCtrl',
            },
            "[email protected]": {
                templateUrl: DjangoProperties.STATIC_URL +  "common_partials/characteristics.html"
            }, 
            "[email protected]": {
                templateUrl: DjangoProperties.STATIC_URL +  "common_partials/attributes.html"
            }, 
            "[email protected]": {
                templateUrl: DjangoProperties.STATIC_URL +  "common_partials/skills.html"
            }, 
            "[email protected]": {
                templateUrl: DjangoProperties.STATIC_URL +  "partials/spells.html"
            }, 
        }
    });
  }]);

Here is my mages.html:

<h1>Mages</h1>
<hr/>
<a ui-sref="mages.list">Show List</a>
<div ui-view></div>

and my mages.detail.html

<h4>{{mage.name}}</h4>
<div ui-view>
  <div ui-view="characteristics"></div>
  <div ui-view="attributes"></div>
  <div ui-view="skills"></div>
  <div ui-view="spells"></div>
</div>

None of these are loaded, just the default 'list' page.

I feel I've gotten muddled over my view names, but I can't figure out what to do to fix them?

Upvotes: 1

Views: 115

Answers (3)

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123861

I would like to show how the view naming is working. There is a working plunker

So, let's have this index.html:

<H1><ui-view name="title" /></H1>

<ul>
  <li><a ui-sref="parent">parent</a>
  <li><a ui-sref="parent.child">parent.child</a>
</ul>

<div ui-view=""></div>

There is one unnamed view, and one named (title). We have two states. and both will be targeting this 'title' view:

  .state('parent', {
      ...
      views : {
        ...
        "title" : {
          template : "parent is setting title inside of index.html"
        }
      }
  })
  .state('parent.child', { 
      ...
      views : {
        ...
        "title@" : {
          template : "CHILD is setting title inside of index.html"
        },
      }              
  })

What we can see, is that parent calls the view "title" (relative name). The reason is, that index.html (root view) is its parent. The absolute name would work as well (and in fact is created behind the scene): "title@"

On the other hand, child must use absolute naming, because it targets view which is not part of the parent... it is grand-parent (root). So the view name is: "title@"

Now, child template, injected into parent is:

<div>

  <h4>Child</h4>

  <hr />

  View A:
  <div ui-view="viewA" ></div>
  View B:
  <div ui-view="viewB" ></div>

</div>

and that means that child state definition now will be:

 .state('parent.child', { 
      ...
      views : {
        "" : {
          templateUrl: 'tpl.child.html',
          controller: 'ChildCtrl',
        },            
        "[email protected]" : {
          template : "<h5>child content of the view A</h5>"
        },
        "[email protected]" : {
          template : "<h5>child content of the view B</h5>"
        }
        ... // title into the root
      }          
 })

So firstly we injected child template into parent unnamed view "": {...

And next we inject some views (existing inside of this child) with absolute naming === using the child full state name "[email protected]"

Check it in action here

Documentation:

Multiple Named Views

...

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.

Upvotes: 0

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123861

There is another working plunker

In case we want to have only two levels

  • mages
  • mages.list
  • mages.deatil

We have to adjust the state def like this:

.state('mages', {
  url: "/mages",
  templateUrl: DjangoProperties.STATIC_URL + "partials/mages.html"
})
.state('mages.list', {
  url: "/list",
  templateUrl: DjangoProperties.STATIC_URL + "partials/mages.list.html",
  controller: 'MageCtrl'
})
.state('mages.detail', {
     url: "/detail/{mageID:int}",
     views:{

        "": {
            templateUrl: DjangoProperties.STATIC_URL +  "partials/mages.detail.html",
            controller: 'MageCtrl',
        },
        "[email protected]" : {
          templateUrl: "tpl.html",
        },
        "[email protected]": {
            //templateUrl: DjangoProperties.STATIC_URL +  "common_partials/characteristics.html"
            template: "common_partials/characteristics.html",
        }, 
        "[email protected]": {
            //templateUrl: DjangoProperties.STATIC_URL +  "common_partials/attributes.html"
            template: "common_partials/attributes.html"
        }, 
        "[email protected]": {
            //templateUrl: DjangoProperties.STATIC_URL +  "common_partials/skills.html"
            template: "common_partials/skills.html"
        }, 
        "[email protected]": {
            //templateUrl: DjangoProperties.STATIC_URL +  "partials/spells.html"
            template: "partials/spells.html"
        }, 
    }
});

And the mages.list.html will be now like this (no place for child detail)

<h3>The mages list</h3>
<h4>{{mage.name}}</h4>

<li><a href="#/mages/detail/1">mages/detail/1</a>
<li><a href="#/mages/detail/2">mages/detail/2</a>
<li><a href="#/mages/detail/3">mages/detail/3</a>
<li><a href="#/mages/detail/4">mages/detail/4</a>

And the mages.detail.html wil be:

<div >

  <a ui-sref="mages.list">back to list</a>

  <div ui-view="state"></div>
  <div ui-view="characteristics"></div>
  <div ui-view="attributes"></div>
  <div ui-view="skills"></div>
  <div ui-view="spells"></div>
</div>

check it here

Upvotes: 1

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123861

I tried to adjust your settings, and show you one possible way.

There is a working plunker

So, these would be new states mages:

.state('mages', {
  url: "/mages",
  templateUrl: DjangoProperties.STATIC_URL + "partials/mages.html"
})
.state('mages.list', {
  url: "/list",
  templateUrl: DjangoProperties.STATIC_URL + "partials/mages.list.html",
  controller: 'MageCtrl'
})

where detail is child of the list

.state('mages.list.detail', {
     url: "/detail/{mageID:int}",
     views:{
       /*
        "@mage.detail": {
            templateUrl: DjangoProperties.STATIC_URL +  "partials/mages.detail.html",
            controller: 'MageCtrl',
        },
        */
        "" : {
          templateUrl: "tpl.html",
        },
        "[email protected]": {
            //templateUrl: DjangoProperties.STATIC_URL +  "common_partials/characteristics.html"
            template: "common_partials/characteristics.html",
        }, 
        "attributes": {
            //templateUrl: DjangoProperties.STATIC_URL +  "common_partials/attributes.html"
            template: "common_partials/attributes.html"
        }, 
        "skills": {
            //templateUrl: DjangoProperties.STATIC_URL +  "common_partials/skills.html"
            template: "common_partials/skills.html"
        }, 
        "spells": {
            //templateUrl: DjangoProperties.STATIC_URL +  "partials/spells.html"
            template: "partials/spells.html"
        }, 
    }
});

And these are two basic tmplates

mages.html (as it was, no change):

<h1>Mages</h1>
<hr/>
<a ui-sref="mages.list">Show List</a>
<div ui-view></div>

The mages.list.html

<h3>The mages list</h3>
<h4>{{mage.name}}</h4>

<li><a href="#/mages/list/detail/1">mages/list/detail/1</a>
<li><a href="#/mages/list/detail/2">mages/list/detail/2</a>
<li><a href="#/mages/list/detail/3">mages/list/detail/3</a>
<li><a href="#/mages/list/detail/4">mages/list/detail/4</a>

<hr /> 

<div >
  <div ui-view=""></div>
  <div ui-view="characteristics"></div>
  <div ui-view="attributes"></div>
  <div ui-view="skills"></div>
  <div ui-view="spells"></div>
</div>

It is now containing the links to detail and also contains the anchor for detail views

Upvotes: 1

Related Questions