Дисплей раскалывает путь с помощью ember - программирование
Подтвердить что ты не робот

Дисплей раскалывает путь с помощью ember

Я хочу показать путь раскалывания с Ember. Как я могу выполнять итерацию по текущему пути?

По-моему, есть два подхода:

Умный путь

ИЗМЕНИТЬ: см. мой ответ ниже

Я сохраняю этот вопрос актуальным с текущим статусом отображения панировочных сухарей. Вы можете просмотреть изменения этого вопроса, чтобы просмотреть историю.

Здесь есть несколько целей:

  • Прослушать изменение маршрута
  • Поиск текущего маршрута
  • отображение списка текущего маршрута
  • отобразить рабочие ссылки на шаги маршрута

контроллер

App.ApplicationController = Ember.Controller.extend({
    needs: ['breadcrumbs'],
    currentPathDidChange: function() {
        path = this.get('currentPath');
        console.log('path changed to: ', path);
        this.get('controllers.breadcrumbs').set('content',this.get('target.router.currentHandlerInfos'));
    }.observes('currentPath')
});
App.BreadcrumbsController = Em.ArrayController.extend({});

маршрутизатор

App.ApplicationRoute = Ember.Route.extend({
    renderTemplate: function() {
        this.render();
        this.render('breadcrumbs', {
            outlet: 'breadcrumbs',
            into: 'application',
            controller: this.controllerFor('breadcrumbs')
        });
    }
});

Шаблон

{{! application template }}
<div class="clearfix" id="content">
    {{outlet "breadcrumbs"}}
    {{outlet}}
</div>

{{! breadcrumbs template }}
<ul class="breadcrumb">
  {{#each link in content}}
    <li>
      <a {{bindAttr href="link.name"}}>{{link.name}}</a> <span class="divider">/</span>
    </li>
  {{/each}}
</ul>

Нынешние проблемы для решения:

  • Когда я перехожу к URL-адресу: #/websites/8/pages/1, вывод для панировок: (я удалил все script -tag placeholders
<ul class="breadcrumb">
  <li>
    <a href="application" data-bindattr-34="34">application</a> <span class="divider">/</span></li>
  <li>
    <a href="sites" data-bindattr-35="35">sites</a> <span class="divider">/</span>
  </li>
  <li>
    <a href="site" data-bindattr-36="36">site</a> <span class="divider">/</span>
  </li>
  <li>
    <a href="pages" data-bindattr-37="37">pages</a> <span class="divider">/</span>
  </li>
  <li>
    <a href="page" data-bindattr-38="38">page</a> <span class="divider">/</span>
  </li>
  <li>
    <a href="page.index" data-bindattr-39="39">page.index</a> <span class="divider">/</span>
  </li>
</ul>
  • URL должен быть допустимым маршрутом
  • Меню теперь жестко закодировано с помощью {{#linkTo}} для маршрутов, я пытался сделать эту динамику, например здесь, но transitionTo не запускает currentPath -observer

Другой способ

Большинство из них те же, что и выше, но есть несколько отличий. Панировочные сухари создаются путем перебора location.hash вместо того, чтобы получать его от маршрутизатора.

ApplicationController становится:

ApplicationController = Ember.Controller.extend({
    needs: ['breadcrumbs'],
    hashChangeOccured: function(context) {
        var loc = context.split('/');
        var path = [];
        var prev;
        loc.forEach(function(it) {
            if (typeof prev === 'undefined') prev = it;
            else prev += ('/'+it)
            path.push(Em.Object.create({ href: prev, name: it }));
        });
        this.get('controllers.breadcrumbs').set('content',path)
    }
});
ready : function() {
    $(window).on('hashchange',function() {
        Ember.Instrumentation.instrument("hash.changeOccured", location.hash);
    });
    $(window).trigger('hashchange');
}

Нам нужно подписаться на пользовательский обработчик в ApplicationRoute

App.ApplicationRoute = Ember.Route.extend({
    setupController: function(controller, model) {
        Ember.Instrumentation.subscribe("hash.changeOccured", {
            before: function(name, timestamp, payload) {
                controller.send('hashChangeOccured', payload);
            },
            after: function() {}
        });
    }
});

Пока альтернативный подход работает лучше всего для меня, но это не очень хороший способ сделать это, потому что, когда вы настраиваете маршрутизатор на использование history вместо location.hash, этот метод больше не будет работать.

4b9b3361

Ответ 1

Основываясь на вашем текущем выпуске breadcrumb, я думаю, у вас есть ошибка в вашем маршрутизаторе.

Следующая команда должна возвращать массив с текущей парой:

App.get('Router.router.currentHandlerInfos');

Ваш маршрутизатор должен быть вложен:

this.resource('page 1', function () {
    this.resource('page 2');
});

Вы можете использовать #linkTo вместо тега a в своей паре, вы получите активный класс бесплатно.

Ответ 2

Я придумал гораздо более простое решение, которое я разместил в Ember discourse.

Ответ 3

Я нашел решение (Ember-way) для отображения панировочных сухарей. Он основан на маршрутизаторе вместо моего location.hash.

Инфраструктура

Сначала нам нужно создать инфраструктуру для панировочных сухарей, прежде чем добавлять или удалять элементы из массива breadcrumbs.

Меню

В моем app.js я определяю a NavItem -объект. Это скелет для всех навигационных элементов. Я использую его для определения моих пунктов меню, но мы также будем использовать его для панировочных сухарей.

App.NavItem = Em.Object.extend({
    displayText: '',
    routeName: ''
});
// define toplevel menu-items
App.dashboardMenuItem = App.NavItem.create({
    displayText: 'Dashboard',
    routePath: 'dashboard',
    routeName: 'dashboard'
});
App.sitesMenuItem = App.NavItem.create({
    displayText: 'Websites',
    routePath: 'sites.index',
    routeName: 'sites'
});

Контроллеры

Нам нужен BreadcrumbsController, чтобы держать панировочные сундуки в центральном месте

App.BreadcrumbsController = Em.ArrayController.extend({
    content: []
});

Мой ApplicationController зависит от BreadcrumbsController

App.ApplicationController = Ember.Controller.extend({
    needs: ['breadcrumbs']
});

BreadcrumbsView - это подпрограмма ApplicationView

представления

App.ApplicationView = Ember.View.extend({
    BreadcrumbsView: Ember.View.extend({
        templateName: 'breadcrumbs',

        init: function() {
            this._super();
            this.set('controller', this.get('parentView.controller.controllers.breadcrumbs'));
        },
        gotoRoute: function(e) {
            this.get('controller').transitionToRoute(e.routePath);
        },

        BreadcrumbItemView: Em.View.extend({
            templateName:'breadcrumb-item',
            tagName: 'li'
        })
    })
});

Шаблоны

В моем приложении -template я вывожу представление с паникой над розеткой

{{view view.BreadcrumbsView}}
{{outlet}}

Я использую Twitter Bootstrap, поэтому моя разметка для моей панировки -template

<ul class="breadcrumb">
  {{#each item in controller.content}}
      {{view view.BreadcrumbItemView itemBinding="item"}}
  {{/each}}
</ul>

патч-элемент -template

<a href="#" {{action gotoRoute item on="click" target="view.parentView"}}>
  {{item.displayText}}
</a> <span class="divider">/</span>

Routing

Нам нужно ответить на маршрутизацию в нашем приложении, чтобы обновить панировочные сухари.

Когда мой SitesRoute (или любой другой маршрут верхнего уровня) активируется, мы нажимаем NavItem на Breadcrumbs, но я также хочу сделать это с остальными моими путями верхнего уровня, поэтому я сначала создаю a TopRoute

App.TopRoute = Em.Route.extend({
    activate: function() {
        this.controllerFor('menu').setActiveModule(this.get('routeName'));
        var menuItem = app.menuItems.findProperty('routeName',this.get('routeName'));
        this.controllerFor('breadcrumbs').get('content').pushObject(menuItem);
    },
    deactivate: function() {
        var menuItem = app.menuItems.findProperty('routeName',this.get('routeName'));
        this.controllerFor('breadcrumbs').get('content').removeObject(menuItem);
    }
});

Все мои пропуски простираются от этого маршрута, поэтому панировочные сухари автоматически обновляются

App.SitesRoute = App.TopRoute.extend();

Для более глубоких уровней он работает почти так же, все, что вам нужно сделать, это использовать крюки activate и deactivate для push/remove объектов из Breadcrumbs

App.SiteRoute = Em.Route.extend({
    activate: function() {
        var site = this.modelFor('site');
        this.controllerFor('breadcrumbs').get('content').pushObject(app.NavItem.create({
            displayText: site.get('name'),
            routePath: 'site',
            routeName: this.get('routeName')
        }));
    },
    deactivate: function() {
        var site = this.modelFor('site');
        this.controllerFor('breadcrumbs').get('content').removeAt(1);   
    }
});