Mvvm 支持自定义 kendo ui 小部件

Posted

技术标签:

【中文标题】Mvvm 支持自定义 kendo ui 小部件【英文标题】:Mvvm support for custom kendo ui widget 【发布时间】:2014-09-16 00:02:38 【问题描述】:

几天前我问了this 问题并得到了一个非常酷的答案。此后我想知道我是否可以使用my custom widget,因为我使用 mvvm 约定的所有标准剑道组件。我必须编辑自定义小部件的哪些部分? 例如:

<div id="dropdowns" data-role="linkeddropdowns" data-period="YEAR" 
    data-bind="year: selectedYear"></div>

谢谢,

【问题讨论】:

试试这些创建小部件的剑道教程:-blogs.telerik.com/kendoui/posts/12-04-03/… 【参考方案1】:

我认为您可能会遇到内部视图模型方法的问题,因为 Kendo UI 往往不擅长嵌套视图模型绑定。 据我所知,所有 Kendo UI 小部件都因此在代码中创建其内部小部件。

旁注:在您的小部件中,您将 DOM id 用于下拉元素 - 如果您要在同一页面上创建多个小部件,这将创建重复项。在这种情况下最好使用类。

要启用year 绑定,您需要custom binder,它可能看起来像这样:

kendo.data.binders.widget.year = kendo.data.Binder.extend(
    init: function (element, bindings, options) 
        kendo.data.Binder.fn.init.call(this, element, bindings, options);

        var that = this;
        that.element.bind("change", function () 
            that.change(); //call the change function
        );
    ,
    refresh: function () 
        var that = this,
            value = that.bindings.year.get();

        this.element.setYear(value);
    ,
    change: function () 
        var value = this.element.getYear();
        this.bindings.year.set(value);
    
);

这适用于提供这些访问器的小部件:

getYear: function () 
    return this._getWidget("year").value();
,

setYear: function (value) 
    this._getWidget("year").value(value);
    console.log(this._getWidget("year"));

完整的小部件示例(注意它没有完全实现 - 它只考虑了年份绑定和期间设置):

(function ($) 
    var kendo = window.kendo,
        ui = kendo.ui,
        Widget = ui.Widget,
        periods = [
             text: "PERIOD: YEAR", value: "YEAR" ,
             text: "PERIOD: QUARTER", value: "QUARTER" 
        ],
        quarters = [
             text: "1. Quarter", value: 1 ,
             text: "2. Quarter", value: 2 ,
             text: "3. Quarter", value: 3 ,
             text: "4. Quarter", value: 4 
        ],
        years = [2011, 2012, 2013, 2014];

    var LinkedDropDowns = Widget.extend(
        init: function (element, options) 
            var that = this,
                periodOption = $(element).data("period");
            if (periodOption) 
                this.options.period = periodOption;
            

            Widget.fn.init.call(that, element, options);
            that._create();

          // make sure view state is correct depending on selected period
          this._getWidget("period").trigger("change");
        ,

        options: 
            name: "LinkedDropDowns",
            period: "YEAR",
            periods: periods,
            year: 2011,
            years: years,
            quarter: 1,
            quarters: quarters,
            selectedYear: 2011
        ,

        onPeriodChange: function (e) 
            switch (e.sender.value()) 
                case "YEAR":
                    $(this._getWidget("year").wrapper).show();
                    $(this._getWidget("quarter").wrapper).hide();
                    break;
                case "QUARTER":
                    $(this._getWidget("year").wrapper).show();
                    $(this._getWidget("quarter").wrapper).show();
                    break;
                default:
                    break;
            
        ,

        onChange: function () 
            // trigger change so the binder knows about it
            this.trigger("change",  sender: this ); 
        ,

        _getWidget: function (name) 
            var el = $(this.element).find("input." + name).first();
            return el.data("kendoDropDownList");
        ,

        _create: function () 
            var that = this;

            // create dropdowns from templates and append them to DOM
            that.periodDropDown = $(that._templates.periodDropDown);
            that.yearDropDown = $(that._templates.yearDropDown);
            that.quarterDropDown = $(that._templates.quarterDropDown);

            // append all elements to the DOM
            that.element.append(that.periodDropDown)
                .append(that.yearDropDown)
                .append(that.quarterDropDown);

            $(this.element).find(".period").kendoDropDownList(
                dataTextField: "text",
                dataValueField: "value",
                value: this.options.period,
                change: this.onPeriodChange.bind(that),
                dataSource: this.options.periods
            );

            $(this.element).find(".year").kendoDropDownList(
                dataSource: this.options.years,
                change: this.onChange.bind(this)
            );

            $(this.element).find(".quarter").kendoDropDownList(
                dataTextField: "text",
                dataValueField: "value",
                dataSource: this.options.quarters

            );
        ,

        _templates: 
            periodDropDown: "<input class='period' />",
            yearDropDown: "<input class='year' style='width: 90px' />",
            quarterDropDown: "<input class='quarter' style='width: 110px' />"
        ,

        getYear: function () 
            return this._getWidget("year").value();
        ,

        setYear: function (value) 
            this._getWidget("year").value(value);
            console.log(this._getWidget("year"));
        
    );

    ui.plugin(LinkedDropDowns);
)(jQuery);

(demo)

【讨论】:

【参考方案2】:

无需对小部件进行额外编码。要启用小部件进行声明式初始化,您可以执行以下操作:

HTML

<div id="dropdowns" data-role="linkeddropdowns" data-period="QUARTER" data-year="2014"></div>

这些数据属性将覆盖小部件中“YEAR”和“2011”的默认选项。

JavaScript

(function() 
  kendo.init($('body'));
)();

不用调用$('#dropdowns').kendoLinkedDropDowns(),只需调用kendo.init(),小部件就会自行处理绑定。

Here 是更新后的工作 JSBin 示例。

【讨论】:

我按照 Lars 在他的回答中的建议从模板中删除了 id 属性。他是对的——你不希望小部件组件上的id 属性可能在页面上多次使用。

以上是关于Mvvm 支持自定义 kendo ui 小部件的主要内容,如果未能解决你的问题,请参考以下文章

如何进一步MVVM Kendo UI小部件?

Kendo UI,使用 MVVM 时如何从 DOM 元素获取小部件对象?

Kendo UI for jQuery使用教程:使用MVVM初始化

Kendo UI Scheduler - MVVM 设置日期

将自定义 CSS 类传递给 Kendo 的下拉小部件

kendo mvvm:如何定义自定义 css 绑定