Mvvm support for custom kendo ui widget

这一生的挚爱 提交于 2019-12-10 11:12:12

问题


A few days before I asked this question and got a really cool answer. Hereafter I wonder if I can use my custom widget as I use all standart kendo components by mvvm convention. And what parts of custom widget do I have to edit? For example:

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

Thanks,


回答1:


I think you may run into problems with the internal view model approach because Kendo UI tends to not be good about nesting view model bindings. As far as I know, all Kendo UI widgets create their internal widgets in code because of that.

Side note: in your widget, you were using DOM ids for the dropdown elements - this would create duplicates if you were to create multiple of your widgets on the same page. It's better to use classes in that case.

To enable a year binding, you'll need a custom binder, which might look something like this:

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

This would work with a widget that provides these accessors:

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

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

Complete widget example (note that it's not fully implemented - it only takes into account the year binding and the period setting):

(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:


No additional coding to the widget is required. To enable the widget for declarative initialization, you can do the following:

HTML

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

These data attributes will override the default options of "YEAR" and "2011" in the widget.

JavaScript

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

Instead of calling $('#dropdowns').kendoLinkedDropDowns(), just call kendo.init() and the widget takes care of binding itself.

Here is the updated working JSBin example.



来源:https://stackoverflow.com/questions/24933598/mvvm-support-for-custom-kendo-ui-widget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!