AngularJS 中具有嵌套状态的嵌套视图 [英] Nested views with nested states in AngularJS

查看:25
本文介绍了AngularJS 中具有嵌套状态的嵌套视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建嵌套状态,但出了点问题,我不知道为什么.

我的 angular 应用中有这些状态:

/client(列出客户)/client/:id(显示客户端)/client/new(新客户)

现在,我正在尝试:

/client/:id/task(列出客户端任务)/client/:id/task/new(为此客户端创建新任务)/client/:id/task/:idTask(显示客户端任务)

所有状态都在工作,但 task 状态没有改变内容.

我的 index.htmlui-view "main":

<标题></标题><边栏></边栏><section class="main-content-wrapper" ng-class="{'main':collapse}"><section id="main-content"><div ui-view="main"></div></节></节></节>

我的 client.tpl.html 带有 ui 视图内容":

<div class="col-md-12"><ul class="面包屑"><li><a href ui-sref="home">首页</a></li><li class="active">客户端</li>

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

我的应用声明:

$stateProvider.状态('/', {网址:'/',templateUrl: '/app/application/application.tpl.html',摘要:真实})//客户.state('客户', {网址:'/客户端',摘要:真实,意见:{'主要的': {templateUrl: '/app/client/client.tpl.html',控制器:'客户端控制器'}}}).state('client.list', {网址:'/列表',意见:{'内容': {templateUrl: '/app/client/client.list.tpl.html',控制器:'ClientListController'}}}).state('client.new', {网址:'/新',意见:{'内容': {templateUrl: '/app/client/client.new.tpl.html',控制器:'ClientNewController'}}}).state('client.show', {网址: '/:id',意见:{'内容': {templateUrl: '/app/client/client.show.tpl.html',控制器:'ClientShowController',}}})

任务状态

//任务.state('client.details', {url: '/:idClient',摘要:真实,意见:{'内容': {templateUrl: '/app/task/task.tpl.html',控制器:'任务控制器'}}}).state('client.details.task', {网址:'/任务',意见:{'内容': {templateUrl: '/app/task/task.list.tpl.html',控制器:'任务列表控制器'}}}).state('client.details.task.new', {网址:'/新',意见:{'内容': {templateUrl: '/app/task/task.new.tpl.html',控制器:'TaskNewController'}}}).state('client.details.task.show', {url: '/:idTask',意见:{'内容': {templateUrl: '/app/task/task.show.tpl.html',控制器:'TaskShowController'}}});

所以,当我点击去:

/客户端/客户端/:ID/客户端/新

一切正常,内容发生变化,但是,当我点击转到:

/client/:id/task/client/:id/task/:idTask/客户端/:id/任务/新

内容没有改变,实际上是内容变空了.

<小时>

更新 1

任务列表的链接在我的侧边栏中,侧边栏是一个指令:

指令:

.directive('sidebar', [function() {返回 {限制:'E',替换:真的,templateUrl: '/common/partials/sidebar.html'};}])

模板:

</一边>

ui-sref中的链接是:/client/10/task

<小时>

解决方案

解决方案出奇的简单,但背后的概念可能有点挑战性.

所以状态定义应该是这样的

客户端根状态没有任何变化.它确实将其视图注入到根状态的 ui-view="main" (index.html)

//客户端.state('客户', {...意见:{'主要的': {templateUrl: '/app/client/client.tpl.html',...}}})

现在,我们有了一级孩子.他们将针对父ui-view=content"(客户端及其模板注入ui-view=main")

.state('client.list', {意见:{'内容': {....}).state('client.new', {网址:'/新',意见:{'内容': {...})...

所以到目前为止,一切正常.下面是一个变化.我们再次尝试将我们的模板注入 ui-view="content" - 很好.但它没有在我们的父级中定义.它处于我们的 祖父 - Client 状态.所以我们跳过了一层.我们必须使用绝对命名来定位视图名称

//任务.state('client.details.task', {意见:{//错误的'内容': {//正确的'内容@客户端':{}).state('client.details.task.new', {意见:{//错误的'内容': {//正确的'内容@客户端':{}})...

现在应该清楚了.如果没有,也许这会有所帮助.第一级孩子,即使使用这个状态定义也能工作

.state('client.list', {意见:{//在职的'内容': {//也工作'内容@客户端':{....})

因为我们只是使用了绝对命名 - 它是为我们开箱即用的(语法糖).如需更多更好的解释,请参阅文档:

查看名称 - 相对名称与绝对名称

小引用:

<块引用>

在幕后,每个视图都被分配一个绝对名称,遵循 viewname@statename 方案,其中 viewname 是视图指令和状态名称中使用的名称是状态的绝对名称,例如联系方式.您还可以选择以绝对语法编写视图名称.

例如,前面的例子也可以写成:

.state('报告',{意见:{'过滤器@':{},'表数据@':{},'图@':{}}})

I'm trying to make nested states, but something is wrong and I can't figure out why.

I have these states in my angular app:

/client (list clients)
/client/:id (show client)
/client/new (new client)

And now, I'm trying to do:

/client/:id/task (list clients tasks)
/client/:id/task/new (create new task for this client)
/client/:id/task/:idTask (show the client task)

All the states are working, but the task states is not changing the content.

My index.html with the ui-view "main":

<section id="container">
    <header></header>
    <sidebar></sidebar>
    <section class="main-content-wrapper" ng-class="{'main':collapse}">
        <section id="main-content">
            <div ui-view="main"></div>
        </section>
    </section>
</section>

My client.tpl.html with the ui-view "content":

<div class="row">
    <div class="col-md-12">
        <ul class="breadcrumb">
            <li><a href ui-sref="home">Home</a></li>
            <li class="active">Clients</li>
        </ul>
    </div>
</div>
<div ui-view="content"></div>

My app states:

$stateProvider
    .state('/', {
        url: '/',
        templateUrl: '/app/application/application.tpl.html',
        abstract: true
    })

    // CLIENT
    .state('client', {
        url: '/client',
        abstract: true,
        views: {
            'main': {
                templateUrl: '/app/client/client.tpl.html',
                controller: 'ClientController'
            }
        }
    })
    .state('client.list', {
        url: '/list',
        views: {
            'content': {
                templateUrl: '/app/client/client.list.tpl.html',
                controller: 'ClientListController'
            }
        }
    })
    .state('client.new', {
        url: '/new',
        views: {
            'content': {
                templateUrl: '/app/client/client.new.tpl.html',
                controller: 'ClientNewController'
            }
        }
    })
    .state('client.show', {
        url: '/:id',
        views: {
            'content': {
                templateUrl: '/app/client/client.show.tpl.html',
                controller: 'ClientShowController',
            }
        }
    })

Tasks states

    // TASKS
    .state('client.details', {
        url: '/:idClient',
        abstract: true,
        views: {
            'content': {
                templateUrl: '/app/task/task.tpl.html',
                controller: 'TaskController'
            }
        }
    })
    .state('client.details.task', {
        url: '/task',
        views: {
            'content': {
                templateUrl: '/app/task/task.list.tpl.html',
                controller: 'TaskListController'
            }
        }
    })
    .state('client.details.task.new', {
        url: '/new',
        views: {
            'content': {
                templateUrl: '/app/task/task.new.tpl.html',
                controller: 'TaskNewController'
            }
        }
    })
    .state('client.details.task.show', {
        url: '/:idTask',
        views: {
            'content': {
                templateUrl: '/app/task/task.show.tpl.html',
                controller: 'TaskShowController'
            }
        }
    });

So, when I click to go to:

/client
/client/:id
/client/new

Everything works fine, the content change, but, when I click to go to:

/client/:id/task
/client/:id/task/:idTask
/client/:id/task/new

The content don't change, actually, the content gets empty.


UPDATE 1

The link to the task list is in my sidebar, sidebar is a directive:

Directive:

.directive('sidebar', [function () {
    return {
        restrict: 'E',
        replace: true,
        templateUrl: '/common/partials/sidebar.html'
    };
}])

Template:

<aside class="sidebar" ng-class="{'sidebar-toggle':collapse}" ng-controller="SidebarController as sidebar">
    <div id="leftside-navigation" class="nano">
        <ul class="nano-content">
            <li class="active">
                <a href ui-sref="home"><i class="fa fa-dashboard"></i><span>Home</span></a>
            </li>
            <li class="sub-menu">
                <a href ng-click="toggle()">
                    <i class="fa fa-users"></i>
                    <span>Clients</span>
                    <i class="arrow fa fa-angle-right pull-right"></i>
                </a>
                <ul style="height: {{height}}px; overflow: hidden;">
                    <li ng-repeat="client in session.clients">
                        <a href ui-sref="client.details.task({id:client.id})">{{client.name}}</a>
                    </li>
                </ul>
            </li>
        </ul>
    </div>
</aside>

The link in ui-sref is: /client/10/task


解决方案

Solution there is surprisingly simple, but the concept behind could be a bit challenging.

So the state definition should be like this

Client root state is without any change. It does inject its view into ui-view="main" of the root state (index.html)

// CLIENT
.state('client', {
    ...
    views: {
        'main': {
            templateUrl: '/app/client/client.tpl.html',
            ...
        }
    }
})

Now, we have first level children. They will target ui-view="content" of their parent (client and its template injected into ui-view="main")

.state('client.list', {
    views: {
        'content': {
    ....
})
.state('client.new', {
    url: '/new',
    views: {
        'content': {
    ...
})
...

So until now, everything is working. Below is a change. We try again inject our templates into ui-view="content" - good. But it is not defined in our parent. It is in our grand-parent - a Client state. So we are skipping one level. We have to use absolute naming for view name targeting

// TASKS
.state('client.details.task', {
    views: {
        // wrong
        'content': {
        // correct
        'content@client': {         
})
.state('client.details.task.new', {
    views: {
        // wrong
        'content': {
        // correct
        'content@client': {         
    }
})
...

Now it should be clear. If not, maybe this could help a bit. The first level children, would work even with this state definition

.state('client.list', {
    views: {
        // working
        'content': {
        // also working
        'content@client': {
    ....
})

Because we just used absolute naming - where the it is done for us out of the box (syntactic sugar). For more and even better explanation, please, see documentation:

View Names - Relative vs. Absolute Names

small cite:

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.

For example, the previous example could also be written as:

.state('report',{
    views: {
      'filters@': { },
      'tabledata@': { },
      'graph@': { }
    }
})

这篇关于AngularJS 中具有嵌套状态的嵌套视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆