当前位置: 首页 > 面试题库 >

如何使用AngularJS + Angular UI Router制作自动动态面包屑

金兴朝
2023-03-14
问题内容

Web应用程序的一个关键组件是面包屑/导航。使用Angular UI
Router,将面包屑元数据放在各个状态中而不是放在控制器中是有意义的。手动为需要的每个控制器创建面包屑对象是一项直截了当的任务,但这也是一个非常麻烦的任务。

我已经看到了一些使用Angular的自动面包屑的解决方案,但是老实说,它们相当原始。某些状态,例如对话框或侧面板,不应更新面包屑,但是如果将当前的附加组件添加到angular,则无法表达这种状态。

另一个问题是面包屑的标题不是静态的。例如,如果转到“用户详细信息”页面,则面包屑标题可能应该是用户的全名,而不是通用的“用户详细信息”。

需要解决的最后一个问题是为父链接使用所有正确的状态参数值。例如,如果您正在查看公司的“用户详细信息”页面,显然您会想知道上级国家需要:companyId

是否有其他插件可以提供这种水平的面包屑支持?如果不是,最好的解决方法是什么?我不想弄乱我的控制器-我将有很多控制器-我想使它尽可能自动化和轻松。

谢谢!


问题答案:

我确实自己解决了一段时间,因为没有可用的东西。我决定不使用该data对象,因为我们实际上不希望面包屑标题由孩子继承。有时会有模态对话框和右侧面板滑入,从技术上讲是“儿童视图”,但它们不应影响面包屑。通过使用breadcrumb对象,我们可以避免自动继承。

对于实际title属性,我正在使用$interpolate。我们可以将面包屑数据与解析范围合并,而不必在其他地方进行解析。在我遇到的所有情况下,我都只想使用resolve作用域,因此效果很好。

我的解决方案也可以处理i18n。

$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.

我不想将面包屑绑定到指令,因为我认为在我的应用程序中可能有多种方式直观显示面包屑。因此,我将其投入了服务:

.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;
        }
    };
})

实际的面包屑指令变得非常简单:

.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>

从此处的屏幕截图中,您可以看到它在两种导航中均能完美运行:

在此处输入图片说明

以及html <title>标签

在此处输入图片说明

PS到Angular UI Team:请立即添加类似的内容!



 类似资料:
  • 问题内容: 看来这个问题已经被问过几次了,但是没有正确的答案。 我的情况:我正在使用ajax(出于某种原因不使用角度路由模板)将模板(带有html和脚本)初始化为div。 index.html(主要) template.html(模板) 当我单击按钮时,它将文件加载到容器中,但是出现错误 错误:[ ng:areq ]参数’TempCtrl’不是函数,未定义 尽管已将其添加到应用控制器中。 我如何动

  • 问题内容: 我有一个现有页面,需要在其中添加一个可以动态加载的控制器的角度应用程序。 这是一个片段,它根据API和我发现的一些相关问题实现了关于如何完成操作的最佳猜测: JSFiddle。请注意,这是对实际事件链的简化,在以上各行之间有各种异步调用和用户输入。 当我尝试运行上述代码时,由$ compile返回的链接器将抛出:。如果我正确地理解了引导程序,那么它返回的注射器应该知道该模块,对吗? 相

  • 问题内容: 因此从Angular 1.1.4开始,您可以拥有一个动态模板网址。从这里, templateUrl-与模板相同,但是从指定的URL加载模板。由于模板加载是异步的,因此在加载模板之前,将暂停编译/链接。 您可以将templateUrl指定为表示URL的字符串,或者指定为使用两个参数tElement和tAttrs(在下面的编译函数api中进行描述)并返回表示URL的字符串值的函数。 我如何

  • 问题内容: 我在制作JApplet并遇到动画问题。 这是我的代码: 有了它,就没有动画:在循环过程中什么也没发生,repaint()方法似乎只在精灵停止移动后才起作用。 我只想将Swing用于此目的,关于如何进行的任何想法? 谢谢阅读。 问题答案: 您应该使用a 来执行动画,而不要使用“线程睡眠”。这是一个很好的链接,可以助您一臂之力:http : //java.sun.com/docs/book

  • 我有一个计划的工作,我想得到固定利率动态,但不能解决如何做到这一点。 FixedRate以毫秒为单位获取值,但我想以小时为单位给出时间。我还试着从属性文件中读取参数并将其相乘,但没有成功。我该怎么做? 我的财产档案也在这里:

  • 问题内容: 我认为此脚本对周围的任何菜鸟都非常感兴趣:)包括我:) 我想要创建的是一个可以在任何文件中使用的小代码,它将生成像这样的面包屑: 如果文件名为“ _website.com/templates/index.php_ ”,则面包屑应显示: ^^链接^^纯文本 如果文件名为“ _website.com/templates/template_some_name.php_ ”,则面包屑应显示: