Дисплей раскалывает путь с помощью 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
, этот метод больше не будет работать.
Ответы
Ответ 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);
}
});