Подтвердить что ты не робот

Как связать активный класс ссылки с помощью нового маршрутизатора Ember?

Я использую Twitter Bootstrap для навигации в своем приложении Ember.js. Bootstrap использует класс active в теге li, который обертывает ссылки навигации, а не устанавливает класс active в самой ссылке.

Ember.js new linkTo helper установит класс active в ссылке, но (насколько я вижу) не предлагает привязываться к этому свойству.

Сейчас я использую этот уродливый подход:

{{#linkTo "inbox" tagName="li"}}
  <a {{bindAttr href="view.href"}}>Inbox</a>
{{/linkTo}}

Это выведет:

<li class="active" href="/inbox"><a href="/inbox">Inbox</a></li>

Это то, что я хочу, но недействительный HTML.

Я также попытался привязать к сгенерированному свойству LinkView active из родительского представления, но если вы это сделаете, родительское представление будет отображаться дважды, прежде чем оно будет вставлено, что приведет к ошибке.

Помимо ручного воссоздания логики, используемой внутренне помощником linkTo для назначения класса active для ссылки, есть ли лучший способ добиться этого эффекта?

4b9b3361

Ответ 1

Вы также можете использовать вложенные ссылки:

{{#link-to "ccprPracticeSession.info" controller.controllers.ccprPatient.content content tagName='li' href=false eventName='dummy'}}
  {{#link-to "ccprPracticeSession.info" controller.controllers.ccprPatient.content content}}Info{{/link-to}}
{{/link-to}}

Ответ 2

Нам определенно нужно более публичное, постоянное решение, но что-то вроде этого должно работать пока.

Шаблон:

<ul>
{{#view App.NavView}}
  {{#linkTo "about"}}About{{/linkTo}}
{{/view}}

{{#view App.NavView}}
  {{#linkTo "contacts"}}Contacts{{/linkTo}}
{{/view}}
</ul>

Определение вида:

App.NavView = Ember.View.extend({
  tagName: 'li',
  classNameBindings: ['active'],

  active: function() {
    return this.get('childViews.firstObject.active');
  }.property()
});

Это зависит от нескольких ограничений:

Я предоставил живой JSBin этой работы.

Ответ 3

Хорошо, я взял отличную идею @alexspeller и преобразовал ее в ember-cli:

приложение/компоненты/ссылка-li.js

export default Em.Component.extend({
    tagName: 'li',
    classNameBindings: ['active'],
    active: function() {
        return this.get('childViews').anyBy('active');
    }.property('[email protected]')
});

В моем навигаторе я:

{{#link-li}}
    {{#link-to "squares.index"}}Squares{{/link-to}}
{{/link-li}}
{{#link-li}}
    {{#link-to "games.index"}}Games{{/link-to}}
{{/link-li}}
{{#link-li}}
    {{#link-to "about"}}About{{/link-to}}
{{/link-li}}

Ответ 4

На основе ответа katz вы можете переопределить свойство active при нажатии на элемент nav parentView.

App.NavView = Em.View.extend({

    tagName: 'li',
    classNameBindings: 'active'.w(),

    didInsertElement: function () {
        this._super();
        var _this = this;
        this.get('parentView').on('click', function () {
            _this.notifyPropertyChange('active');
        });
    },

    active: function () {
        return this.get('childViews.firstObject.active');
    }.property()
});

Ответ 5

Я только что написал компонент, чтобы сделать это немного приятнее:

App.LinkLiComponent = Em.Component.extend({
  tagName: 'li',
  classNameBindings: ['active'],
  active: function() {
    return this.get('childViews').anyBy('active');
  }.property('[email protected]')
});

Em.Handlebars.helper('link-li', App.LinkLiComponent);

Использование:

{{#link-li}}
  {{#link-to "someRoute"}}Click Me{{/link-to}}
{{/link-li}}

Ответ 6

Я воссоздал логику, используемую внутренне. Другие методы казались более хаки. Это также облегчит повторное использование логики в других местах, где мне может не понадобиться маршрутизация.

Используется как это.

{{#view App.LinkView route="app.route" content="item"}}{{item.name}}{{/view}}

App.LinkView = Ember.View.extend({
    tagName: 'li',
    classNameBindings: ['active'],
    active: Ember.computed(function() {
      var router = this.get('router'),
      route = this.get('route'),
      model = this.get('content');
      params = [route];

      if(model){
        params.push(model);
      }

      return router.isActive.apply(router, params);
    }).property('router.url'),
    router: Ember.computed(function() {
      return this.get('controller').container.lookup('router:main');
    }),
    click: function(){
        var router = this.get('router'),
        route = this.get('route'),
        model = this.get('content');
        params = [route];

        if(model){
            params.push(model);
        }

        router.transitionTo.apply(router,params);
    }
});

Ответ 7

Вы можете пропустить расширение представления и использовать следующее.

{{#linkTo "index" tagName="li"}}<a>Homes</a>{{/linkTo}}

Даже без href Ember.JS все равно будет знать, как подключиться к элементам LI.

Ответ 8

Для этой же проблемы я пришел с решением на основе jQuery, не уверенным в производительности, но он работает из коробки. Я снова открываю Ember.LinkView и расширил его.

Ember.LinkView.reopen({
    didInsertElement: function(){
        var el = this.$();

        if(el.hasClass('active')){
            el.parent().addClass('active');
        }

        el.click(function(e){
            el.parent().addClass('active').siblings().removeClass('active');
        });
    }
});

Ответ 9

Текущие ответы на момент написания датированы. В более поздних версиях Ember, если вы используете {{link-to}}, он автоматически устанавливает класс 'active' в элементе <a>, когда текущий маршрут соответствует целевой ссылке.

Так что просто напишите свой css с ожиданием, что <a> будет иметь active, и он должен сделать это из коробки.

К счастью эта функция добавлена. Весь материал, который был необходим для решения этой "проблемы" ранее, довольно нелепо.