Kendo-Knockout:在kendo网格中调用模板中的方法是在“父”范围内

时间:2013-01-24 20:12:14

标签: javascript knockout.js kendo-ui

我正在使用控制后代绑定的自定义绑定。这是我的代码:

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.net mvc 4应用程序中完美运行。有关于此的任何想法?

更新

我能够做到这样的工作:

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

但我不太喜欢我的模板中的这段代码。也许有更灵活的解决方案?

1 个答案:

答案 0 :(得分:1)

基于“dataBound”处理程序,整个网格的上下文是FranchiseDetailsViewModel

您必须按照提议的方式将其称为:languagesInfoViewModel().onLanguageSelected(&quot;#=Language#&quot;)

或者您可以考虑尝试使用Knockout-Kendo现在支持的行级KO模板。