0

私は次のマークアップを持っています:

<div id="metro-hub">
    <h1 id="hub-title" data-bind="text: hubTitle" class="hub-title">@Model.HubTitle</h1>
    <div id="hubWrapper" data-root-url="/Root" data-bind="html: currentHub"></div>
</div>

KnockoutJSを使用してviewModelJavaScriptオブジェクトをビューにバインドしています。また、サーバー上のサイトマップにナビゲーションを接続するためのカスタムバインディングを作成しました。以下は私がこれまでに得たものからのいくつかの抜粋です:

var MetroPageViewModel = function () {
    var self = this;

    self.currentHub = ko.observable();
    self.viewPortData = ko.observable();
    self.hubTitle = ko.observable();

    self.renderHub = function (rootUrl) {
        console.log(rootUrl);
        $.ajax({
            url: '/Base/NewHub',
            type: 'get',
            data: {
                url: rootUrl
            },
            success: function (data) {
                if (data) {
                    var wrappedData = $(data);
                    var newHubContent = wrappedData.find('ul');
                    var title = wrappedData.find('input.metro-hub-title').val();
                    self.hubTitle(title);
                    self.currentHub(newHubContent); //THIS IS THE LINE THAT DOES NOT WORK
                }
            }
        });
    };

    self.initialize = function () {
        var url = $('#hubWrapper').data('root-url');
        self.renderHub(url);
    };
};

$(function () {
    var viewModel = new MetroPageViewModel();
    ko.applyBindings(viewModel);
    viewModel.initialize();
});

そして、これがSammy.jsライブラリを使用してURLハッシュに基づいてルーティングを行うカスタムバインディングです。

ko.bindingHandlers.metroHub = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var menuItems = $(element).find('li');
        Sammy(function () {
            var $this = this;
            menuItems.each(function (index, elem) {
                $this.get('#/' + $(elem).data('link-name'), function () {
                    var numChildren = $(elem).data('num-children');
                    if (numChildren > 0) {
                       var rootUrl = (elem).data('source-url');
                       viewModel.renderHub(rootUrl);
                    } else {
                        var dataSource = $(elem).data('source-url');
                        $.ajax({
                            url: dataSource,
                            type: 'get',
                            success: function (data) {
                                if (data) {
                                    viewModel.viewPortData(data);
                                }
                            }
                        });
                    }
                });
            });
            var firstItem = menuItems[0];
            var itemRoute = '#/' + $(firstItem).data('link-name');
            $this.get('', function () { this.app.runRoute('get', itemRoute) });
        }).run();
    }
};

サーバーから返されるデータは次のとおりです。

<div><ul class="metro-menu" data-bind="metroHub: true"><li data-link-name="Home" data-num-children="0" data-source-url="/Navigation/Item1"><a href="#/Home">Home</a></li><li data-link-name="Products" data-num-children="2" data-source-url="/Navigation/Item2"><a href="#/Products">Products</a></li><li data-link-name="Services" data-num-children="0" data-source-url="/Navigation/Item3"><a href="#/Services">Services</a></li></ul>
<input class="metro-hub-title" type="hidden" value="this is a hub title"></input>
<input class="hasParentNode" type="hidden" value="False"></input>
</div>

アップデート:

updateここで問題となるのは、メソッドのAJAXコールバックがrenderHub()返されると、カスタムバインディングコールバックがトリガーされないことです。バインディングなどを強制するために何らかのメソッドを呼び出す必要がありますか?

何かご意見は?

4

1 に答える 1

0

そのコントロールが更新されているため、親コンテナーに update-binding を配置する必要があるかもしれません。

更新に応答する必要がある古い div が新しい html に完全に置き換えられているため、更新が実行されていないと思います。

更新と同じコードを使用してバインドに init 関数を作成することで、私が正しいかどうかを簡単に確認できます。

于 2012-08-14T13:21:47.633 に答える