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
クラスをリンクに割り当てる以外に、この効果を実現するためのより良い方法はありますか?
ネストされたリンク先を使用することもできます。
{{#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}}
私たちは間違いなくもっと公的で恒久的な解決策を必要としていますが、今のところこのようなものはうまくいくはずです。
テンプレート:
<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 を提供しました。
さて、私は@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}}
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()
});
これを少し良くするためのコンポーネントを作成しました。
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}}
内部で使用するロジックを再作成しました。他の方法はもっとハックなようでした。これにより、ルーティングが不要な他の場所でロジックを再利用しやすくなります。
このように使用されます。
{{#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);
}
});
ビューの拡張をスキップして、以下を使用できます。
{{#linkTo "index" tagName="li"}}<a>Homes</a>{{/linkTo}}
Hrefがなくても、Ember.JSはLI要素にフックする方法を知っています。
執筆時点での現在の回答は日付が付けられています。それ以降のバージョンのEmber {{link-to}}
を使用している場合、現在のルートがターゲットリンクと一致すると、'active'
要素に<a>
クラスが自動的に設定されます。
したがって、<a>
にactive
が含まれることを期待して、cssを記述してください。これは、すぐに実行できるはずです。
その機能が追加されたのは幸運です。この「問題」を事前に解決するために必要だったここにあるものはすべて、かなりばかげています。
ここでの同じ問題について、パフォーマンスのペナルティについてはよくわからない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');
});
}
});