14

Ember で崩れたパスを表示したい。現在のパスを反復するにはどうすればよいですか?

私の意見では、2 つのアプローチがあります。

エンバーウェイ

編集:以下の私の答えを見てください

パンくずリストを表示する現在のステータスで、この質問を最新の状態に保ちます。この質問のリビジョンを参照して、履歴を確認できます。

ここにはいくつかの目標があります。

  1. ルート変更時にリッスン
  2. 現在のルートを見つける
  3. 現在のルートのリストを表示する
  4. ルート内のステップへの作業リンクを表示する

コントローラ

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と、ブレッドクラムの出力は次のようになります: (すべてのスクリプト タグ プレースホルダーを削除しました
<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}}のように動的にしようとしましたが、 -observerをトリガーしません。transitionTocurrentPath

反対に

ほとんどは上記と同じですが、いくつかの違いがあります。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なるため、これは良い方法ではありません。

4

3 に答える 3

3

現在のブレッドクラムの出力に基づいて、ルーターにエラーがあると思います。

次のコマンドは、現在のブレッドクラムを含む配列を返す必要があります。

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

ルーターはネストする必要があります。

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

#linkToブレッドクラムでタグの代わりに使用できますa。アクティブなクラスを無料で取得できます。

于 2013-03-27T19:33:26.110 に答える
1

パンくずリストを表示する ( Ember-way ) ソリューションを見つけました。私の代わりにルーターに基づいていますlocation.hash

インフラストラクチャー

パンくず配列にアイテムを追加または削除する前に、まずパンくずリストのインフラストラクチャを作成する必要があります。

メニュー

app.js で -object を定義し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']
});

BreadcrumbsViewApplicationViewのサブビューです

ビュー

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

テンプレート

私のアプリケーションテンプレートでは、アウトレットの上にブレッドクラムビューを出力します

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

私は Twitter Bootstrap を使用しているので、ブレッドクラムのマークアップ-template は

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

breadcrumb -itemテンプレート

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

ルーティング

ブレッドクラムを更新するには、アプリのルーティングに応答する必要があります。

SitesRoute (またはその他のトップレベル ルート) がアクティブ化されたら、NavItem を Breadcrumbs にプッシュしますが、残りのトップレベル ルートでもそれを行いたいので、最初に 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フックを使用して、ブレッドクラムからオブジェクトをプッシュ/削除することだけです。

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);   
    }
});
于 2013-04-05T13:04:59.420 に答える