web-dev-qa-db-ja.com

新しいEmberルーターを使用してリンクのアクティブクラスにバインドするにはどうすればよいですか?

Ember.jsアプリのナビゲーションにTwitter Bootstrapを使用しています。Bootstrapは、設定するのではなく、ナビゲーションリンクをラップするactiveタグのliクラスを使用しますリンク自体のactiveクラス。

Ember.jsの新しいlinkToヘルパーはリンクに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プロパティを親ビューからバインドしようとしましたが、そうすると、親ビューが挿入される前に2回レンダリングされ、エラーが発生します。

linkToヘルパーが内部で使用するロジックを手動で再作成してactiveクラスをリンクに割り当てる以外に、この効果を実現するためのより良い方法はありますか?

22
Nick Ragaz

ネストされたリンク先を使用することもできます。

{{#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}}
8
pjlammertyn

私たちは間違いなくもっと公的で恒久的な解決策を必要としていますが、今のところこのようなものはうまくいくはずです。

テンプレート:

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

これは、いくつかの制約に依存しています。

  • ナビゲーションビューには、単一の静的な子ビューが含まれています
  • <li>sのビューを使用できます。 JavaScript定義またはハンドルバーからビューの要素をカスタマイズする方法については、多くの詳細があります ドキュメント内

私はこの作品の ライブJSBin を提供しました。

27
Yehuda Katz

さて、私は@alexspellerの素晴らしいアイデアを採用し、それをember-cliに変換しました。

app/components/link-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}}
9
Adam Klein

Katzの回答に基づいて、nav要素のactiveがクリックされたときに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()
});
6
Ilia Choly

これを少し良くするためのコンポーネントを作成しました。

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}}
5
alexspeller

内部で使用するロジックを再作成しました。他の方法はもっとハックなようでした。これにより、ルーティングが不要な他の場所でロジックを再利用しやすくなります。

このように使用されます。

{{#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);
    }
});
2
Sean Smith

ビューの拡張をスキップして、以下を使用できます。

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

Hrefがなくても、Ember.JSはLI要素にフックする方法を知っています。

1
Andy Jarrett

執筆時点での現在の回答は日付が付けられています。それ以降のバージョンのEmber {{link-to}}を使用している場合、現在のルートがターゲットリンクと一致すると、'active'要素に<a>クラスが自動的に設定されます。

したがって、<a>activeが含まれることを期待して、cssを記述してください。これは、すぐに実行できるはずです。

その機能が追加されたのは幸運です。この「問題」を事前に解決するために必要だったここにあるものはすべて、かなりばかげています。

0
Purrell

ここでの同じ問題について、パフォーマンスのペナルティについてはよくわからない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');
        });
    }
});
0
Dimuthu Nilanka