如何使自动动态面包屑用AngularJS +角UI路由器 [英] How to make Automated Dynamic Breadcrumbs with AngularJS + Angular UI Router

查看:1751
本文介绍了如何使自动动态面包屑用AngularJS +角UI路由器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到Web应用程序的一个关键组件是面包/导航。具有角UI路由器,这将是有意义的把面包屑的元数据与各个国家,而不是在你的控制器。手动创建面包屑对象为每个在需要的地方控制器是一个简单的任务,但它也是一个非常混乱的。

One key component to web applications is breadcrumbs/navigation. With Angular UI Router, it would make sense to put the breadcrumb metadata with the individual states, rather than in your controllers. Manually creating the breadcrumbs object for each controller where it's needed is a straight-forward task, but it's also a very messy one.

我已经看到了与角自动面包屑的一些解决方案,但说实话,他们是相当原始。一些州,如对话框或侧面板不应该更新面包屑,但与目前的插件,以棱角分明,没有办法给前preSS的。

I have seen some solutions for automated Breadcrumbs with Angular, but to be honest, they are rather primitive. Some states, like dialog boxes or side panels should not update the breadcrumbs, but with current addons to angular, there is no way to express that.

另一个问题是,面包屑的标题是不是静态的。例如,如果你去一个用户详细信息页面,面包屑标题也许应该是用户的全名,而不是一个通用的用户详细信息。

Another problem is that titles of breadcrumbs are not static. For example, if you go to a User Detail page, the breadcrumb title should probably be the user's Full Name, and not a generic "User Detail".

这需要使用所有正确的状态参数值的父环节要解决的最后一个问题。例如,如果您是从公司看一个用户详细信息页面,很明显,你会想知道父状态需要一个:companyId

The last problem that needs to be solved is using all of the correct state parameter values for parent links. For example, if you're looking at a User detail page from a Company, obviously you'll want to know that the parent state requires a :companyId.

在那里任何角度插件提供这种级别的面包屑支持?如果不是,是去了解它的最佳方式?我不想弄乱我的控制器 - 我将有很多人 - 我希望把它自动化和无痛尽可能

Are there any addons to angular that provide this level of breadcrumbs support? If not, what is the best way to go about it? I don't want to clutter up my controllers - I will have a lot of them - and I want to make it as automated and painless as possible.

谢谢!

推荐答案

我这样做解决了自己一段时间回来,因为没有什么是可用的。我决定不使用数据对象,因为我们实际上并不希望我们的面包屑职称儿童继承。有时有模态对话框,右面板,在滑动在技术上的孩子的意见,但他们不应该影响到面包屑。通过使用痕迹对象,而不是我们能避免自动继承。

I did solve this myself awhile back, because nothing was available. I decided to not use the data object, because we don't actually want our breadcrumb titles to be inherited by children. Sometimes there are modal dialogs and right panels that slide in that are technically "children views", but they shouldn't affect the breadcrumb. By using a breadcrumb object instead, we can avoid the automatic inheritance.

有关实际标题属性,我使用 $插值。我们可以不必做解决了不同的地方与决心范围结合我们的面包屑的数据。在所有的情况下,我有,我只是想反正用的决心范围,所以这个作品非常好。

For the actual title property, I am using $interpolate. We can combine our breadcrumb data with the resolve scope without having to do resolves in a different place. In all of the cases I had, I just wanted to use the resolve scope anyway, so this works very well.

我的解决方案也可以处理国​​际化了。

My solution also handles i18n too.

$stateProvider
    .state('courses', {
        url: '/courses',
        template: Templates.viewsContainer(),
        controller: function(Translation) {
            Translation.load('courses');
        },
        breadcrumb: {
            title: 'COURSES.TITLE'
        }
    })
    .state('courses.list', {
        url: "/list",
        templateUrl: 'app/courses/courses.list.html',
        resolve: {
            coursesData: function(Model) {
                return Model.getAll('/courses');
            }
        },
        controller: 'CoursesController'
    })
    // this child is just a slide-out view to add/edit the selected course.
    // It should not add to the breadcrumb - it's technically the same screen.
    .state('courses.list.edit', {
        url: "/:courseId/edit",
        templateUrl: 'app/courses/courses.list.edit.html',
        resolve: {
            course: function(Model, $stateParams) {
                return Model.getOne("/courses", $stateParams.courseId);
            }
        },
        controller: 'CourseFormController'
    })
    // this is a brand new screen, so it should change the breadcrumb
    .state('courses.detail', {
        url: '/:courseId',
        templateUrl: 'app/courses/courses.detail.html',
        controller: 'CourseDetailController',
        resolve: {
            course: function(Model, $stateParams) {
                return Model.getOne('/courses', $stateParams.courseId);
            }
        },
        breadcrumb: {
            title: '{{course.name}}'
        }
    })
    // lots more screens.

我不想面包屑绑在一条指令,因为我觉得有可能是显示我的应用程序在视觉上的面包屑的多种方式。于是,我把它变成一个服务:

I didn't want to tie the breadcrumbs to a directive, because I thought there might be multiple ways of showing the breadcrumb visually in my application. So, I put it into a service:

.factory("Breadcrumbs", function($state, $translate, $interpolate) {
    var list = [], title;

    function getProperty(object, path) {
        function index(obj, i) {
            return obj[i];
        }

        return path.split('.').reduce(index, object);
    }

    function addBreadcrumb(title, state) {
        list.push({
            title: title,
            state: state
        });
    }

    function generateBreadcrumbs(state) {
        if(angular.isDefined(state.parent)) {
            generateBreadcrumbs(state.parent);
        }

        if(angular.isDefined(state.breadcrumb)) {
            if(angular.isDefined(state.breadcrumb.title)) {
                addBreadcrumb($interpolate(state.breadcrumb.title)(state.locals.globals), state.name);
            }
        }
    }

    function appendTitle(translation, index) {
        var title = translation;

        if(index < list.length - 1) {
            title += ' > ';
        }

        return title;
    }

    function generateTitle() {
        title = '';

        angular.forEach(list, function(breadcrumb, index) {
            $translate(breadcrumb.title).then(
                function(translation) {
                    title += appendTitle(translation, index);
                }, function(translation) {
                    title += appendTitle(translation, index);
                }
            );
        });
    }

    return {
        generate: function() {
            list = [];

            generateBreadcrumbs($state.$current);
            generateTitle();
        },

        title: function() {
            return title;
        },

        list: function() {
            return list;
        }
    };
})

实际的痕迹指令然后就变得很简单:

The actual breadcrumb directive then becomes very simple:

.directive("breadcrumbs", function() {
    return {
        restrict: 'E',
        replace: true,
        priority: 100,
        templateUrl: 'common/directives/breadcrumbs/breadcrumbs.html'
    };
});

和模板:

<h2 translate-cloak>
    <ul class="breadcrumbs">
        <li ng-repeat="breadcrumb in Breadcrumbs.list()">
            <a ng-if="breadcrumb.state && !$last" ui-sref="{{breadcrumb.state}}">{{breadcrumb.title | translate}}</a>
            <span class="active" ng-show="$last">{{breadcrumb.title | translate}}</span>
            <span ng-hide="$last" class="divider"></span>
        </li>
    </ul>
</h2>

从截图在这里,你可以看到它完美的作品在这两个导航:

From the screenshot here, you can see it works perfectly in both the navigation:

还有HTML &LT;标题&GT; 标签:

PS到角UI团队:请添加类似这样的开箱

PS to Angular UI Team: Please add something like this out of the box!

这篇关于如何使自动动态面包屑用AngularJS +角UI路由器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆