0

I have states mentioned like this

 $stateProvider
        .state('dashboard', {
            url: "/dashboard",
            views: {
                content: { templateUrl: "/dashboard/index" }
            }
        }).state('accounts', {
            url: "/accounts",
            views: {
                'content': { templateUrl: "/accounts/index" }
            }
        })
        .state('accounts.add', {
            url: "/add",
            views: {
                'content': { templateUrl: "/accounts/add" }
            }
        });

and the URLS are

<a class="list-group-item submenu" ui-sref="accounts">Service Users</a>
<a class="list-group-item submenu" ui-sref="accounts.add">Add User</a>

I am using asp.net Mvc so my Controller which serves the templates currently looks like this

 public class AccountsController : Controller
{
    //
    // GET: /Accounts/
    public ActionResult Index()
    {
        return Request.IsAjaxRequest() ? (ActionResult)PartialView("_Icons") : View();
    }   

    public ActionResult Add()
    {
        return Request.IsAjaxRequest() ? (ActionResult)PartialView("_Add") : View();
    }
}

But whenever I make request to the state accounts.add then it always calls the accounts state .And renders the _icons view which is nothing but a partial view as _icons.cshtml. I can see in firebug that url has been called but it never gets rendered . WHY ????

The firebug output is something like this

GET http://localhost:2060/accounts/index 200 OK 2ms
GET http://localhost:2060/accounts/add 200 OK 5ms

This is what happens when I click ui-sref="accounts.add" and ends up rendering the index action . Can someone tell me why is this happening ? It shouldn't be happening . Is there something which I am missing out as convention from ui-router ?

1 Answer 1

0

I've created a plunker showing/explaining the issue.

The point is, that this child state:

.state('accounts.add', {
    url: "/add",
    views: {
        'content': { templateUrl: "/accounts/add" }
    }

has the same view name as its parent: 'content'. This in fact does not mean, that they target the same view. No - child is searching for a view in a Parent - with the same name content.

The target for the parent state (accounts) is the Index.html (in ASP.NET MVC /home/):

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

The target for the child state (accounts.add) is the templateUrl: "/dashboard/index":

<div>
  ... parent content ...
  ... and here is the place holder for child state (with the same name)
  ... "content"
  <div ui-view="content" ></div>
</div>

The way how to target the root ui-view="content" (index.html) is to use absolute naming. In the plunker I used Insert state for that:

 .state('accounts.insert', {
     url: "/insert",
     views: {
         'content@': { templateUrl: "accounts.insert.tpl.html" }
     }

Where in the view name 'content@' the @ i is the way how to target the root. Please check the documentation for more details:

Small extract:

views: {
    ////////////////////////////////////
    // Relative Targeting             //
    // Targets parent state ui-view's //
    ////////////////////////////////////

    // Relatively targets the 'detail' view in this state's parent state, 'contacts'.
    // <div ui-view='detail'/> within contacts.html
    "detail" : { },            

    // Relatively targets the unnamed view in this state's parent state, 'contacts'.
    // <div ui-view/> within contacts.html
    "" : { }, 

    ///////////////////////////////////////////////////////
    // Absolute Targeting using '@'                      //
    // Targets any view within this state or an ancestor //
    ///////////////////////////////////////////////////////

    // Absolutely targets the 'info' view in this state, 'contacts.detail'.
    // <div ui-view='info'/> within contacts.detail.html
    "[email protected]" : { }

    // Absolutely targets the 'detail' view in the 'contacts' state.
    // <div ui-view='detail'/> within contacts.html
    "detail@contacts" : { }

    // Absolutely targets the unnamed view in parent 'contacts' state.
    // <div ui-view/> within contacts.html
    "@contacts" : { }

    // absolutely targets the 'status' view in root unnamed state.
    // <div ui-view='status'/> within index.html
    "status@" : { }
Sign up to request clarification or add additional context in comments.

2 Comments

So in a manner when /account renders ... its searching the content view inside that outside ui-view which had content view name i I have understood correctly . Is tht so ? your idea is working fine . I am just clarifying my understanding .
You are right: I would put it this way: State defines content of the views defined in its parent... unless more precise (@) naming is used. This way, we can even target views, defined in current state (e.g. hint@accounts could be defined in one of the *main accounts views)* But yes, now you understand that clearly ;) Enjoy ui-router ;)

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.