0

子孫バインディングを制御するカスタムバインディングを使用しています。これが私のコードです:

HTML:

<div>
 <div data-bind="withProperties: languagesInfoViewModel()">

          <div id="languageListGrid" data-bind="kendoGrid: { data: languageViewModels, columns: [ 
                    { 
                        template: '<a href=\'\' data-bind=\'click: function() { $parent.onLanguageSelected(&quot;#=Language#&quot;) }\'>#=Language#</a>', 
                        field: 'Language', 
                        title: 'Language',
                        width: 50
                    }

                    ], 
                scrollable: false, sortable: true, pageable: false }, preventBinding: true"
        style="height: 380px"></div>


        <button data-bind="click: showLanguageDetails">Show Language Details</button>
    <div class="hidden" data-bind="withProperties: selectedLanguageViewModel()">
              <form id="languageDetailsForm" action=" ">

                  <div data-bind="kendoWindow: {isOpen: isOpenPopUp, title:'Language', width: 400, height: 200, modal: true }">
                            test
                            <button id="cancelLanguage" class="k-button" data-bind="click: cancelLanguage">Cancel</button>
                  </div>
              </form>
    </div>
 </div>

Javascript

$(function () {
ko.bindingHandlers.preventBinding = {
    init: function () {
        return {
            controlsDescendantBindings: true
        };
    }
};

ko.bindingHandlers.withProperties = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        var childViewModel = valueAccessor();

        childViewModel.isOpen.subscribe(function (isOpen) {
            if (isOpen) {
                var innerBindingContext = bindingContext.extend(childViewModel);
                ko.applyBindingsToDescendants(innerBindingContext, element);
            };
        });

        return { controlsDescendantBindings: true };
    }
};

ko.bindingHandlers.kendoGrid.options.dataBound = function (data) {
    var body = this.element.find("tbody")[0];

    if (body) {
        ko.applyBindings(ko.dataFor(body), body);
    }
};

var FranchiseInitializer = function () {

    var self = this;

    var initialize = function () {
        var franchiseDetailsViewModel = new FranchiseDetailsViewModel();
        ko.applyBindings(franchiseDetailsViewModel);
        franchiseDetailsViewModel.open();
    };

    initialize();
};

var FranchiseDetailsViewModel = function () {

    var self = this;

    var initialize = function () {
        self.languagesInfoViewModel(new LanguageListViewModel(self));
    };

    self.languagesInfoViewModel = ko.observable();

    self.open = function () {
        self.isOpen(true);
        self.languagesInfoViewModel().open();
    };
    self.isOpen = ko.observable(false);


    initialize();
};

var LanguageListViewModel = function (franchise) {

    var self = this;

    var initialize = function () {
        var languageViewModel = new LanguageDetailsViewModel('English', franchise);
        self.languageViewModels.push(languageViewModel);
        var languageViewModel1 = new LanguageDetailsViewModel('Spanish', franchise);
        self.languageViewModels.push(languageViewModel1);
        self.selectedLanguageViewModel(languageViewModel);
    };

    self.languageViewModels = ko.observableArray([]);
    self.selectedLanguageViewModel = ko.observable();

    self.open = function () {
        self.isOpen(true);
    };
    self.isOpen = ko.observable(false);

    self.showLanguageDetails = function () {
        self.onLanguageSelected("English");
    };

    var getLanguageViewModel = function (language) {
        return self.languageViewModels().filter(
            function (element, index, array) {
                return (element.Language() == language);
            })[0];
    };

    self.onLanguageSelected = function (selectedLanguage) {
        var languageViewModel = getLanguageViewModel(selectedLanguage);
        self.selectedLanguageViewModel(languageViewModel);
        self.selectedLanguageViewModel().open();
    };

    initialize();
};

var LanguageDetailsViewModel = function (lang, franchise) {
    var self = this;

    var closePopUp = function () {
        self.isOpen(false);
        self.isOpenPopUp(false);
    };

    self.isOpenPopUp = ko.observable(false);
    self.Language = ko.observable(lang);

    self.open = function () {
        self.isOpen(true);
        self.isOpenPopUp(true);
    };
    self.isOpen = ko.observable(false);

    self.cancelLanguage = function () {
        closePopUp();
    };
};

var initialize = new FranchiseInitializer();

私は次の問題を抱えています:

グリッドから言語を選択すると、onLanguageSelected関数が実行されます。しかし、エラーが発生します'onLanguageSelected' is undefined。私はそれをデバッグし、グリッドをクリックするとFranchiseDetailsViewModel、ではなく、で ある親コンテキストにいるようLanguageListViewModelです。テンプレートで$child.onLanguageSelectedのようなものを言うことができません。どうすればこれを修正できますか?

フィドル

http://jsfiddle.net/2Qnv7/16/

そして奇妙なことに、Show language detailsボタンをクリックするとポップアップウィンドウが開くはずですが、アニメーションだけが表示されてフリーズします。奇妙なことに、それは私のasp.netmvc4アプリケーションで完全に機能します。これについて何かアイデアはありますか?

アップデート:

私はこのような仕事をすることができました:

languagesInfoViewModel().onLanguageSelected(&quot;#=Language#&quot;)

しかし、テンプレートのこのコードはあまり好きではありません。たぶんもっと柔軟な解決策がありますか?

4

1 に答える 1

1

「dataBound」ハンドラーに基づいて、グリッド全体のコンテキストはあなたのものFranchiseDetailsViewModelです。

あなたはそれをあなたの提案されたように呼ぶ必要があるでしょう:languagesInfoViewModel().onLanguageSelected(&quot;#=Language#&quot;)

または、Knockout-Kendoで現在サポートされている行レベルのKOテンプレートの使用を検討することもできます。

于 2013-01-25T16:27:15.353 に答える