This is a migrated thread and some comments may be shown as answers.

Retrieving the view model (ObservableObject) within a custom widget

3 Answers 399 Views
MVVM
This is a migrated thread and some comments may be shown as answers.
Jack
Top achievements
Rank 2
Iron
Jack asked on 18 Sep 2012, 09:12 AM
Hello,

I am exploring building mvvm custom widgets. Although there is a clear example using a dataSource in the blogs, I want to bind my widget to an ObservableObject viewmodel.

My view model is simple:
var viewModel = kendo.observable({
    message: {type:"info", text: "Hello World!"}
});

My custom widget shall display an information box with an icon defined by the type (info, warning, error, success) and the text message like in the resulting code below (styles not included).
<div id="myMessageBox">
    <img src="./images/infoIcon.png" alt="Hello World!" /><span>Hello World!</span>
</div>

To achieve that, the body of my web page looks like this:
<body>
    <div id="myMessageBox" data-role="infobox" data-type="message.type" data-text="message.text"></div>
</body>

I have some script to bind the view model to the body:
kendo.bind($("body"), viewModel);

and I have implemented my custom widget as follows:
; (function ($, undefined) {
 
    "use strict";
 
    var kendo = window.kendo,
        ui = kendo.ui,
        Widget = ui.Widget;
 
    var InfoBox = Widget.extend({
 
        init: function (element, options) {
            var that = this;
            options = options || {};
            kendo.ui.Widget.fn.init.call(that, element, options);
            that._infoBox();
        },
 
        options: {
            name: "InfoBox",
            type: "info", //warning, error, success
            text: 'Default message for an information box',
            autoBind: true
        },
 
        type: function (value) {
            var that = this;
            if (value) {
                //check value is info, warning, error or success
                that.options.type = value;
                //that._refresh();
                return;
            }
            else {
                return that.options.type;
            }
        },
 
        text: function (value) {
            var that = this;
            if (value) {
                //check value is of type string
                that.options.text = value;
                //that._refresh();
                return;
            }
            else {
                return that.options.text;
            }
        },
 
        _infoBox: function () {
 
            var that = this;
            that._refresh();
        },
 
        _template: '<img src="{0}" alt="#:{1}#" /><span>#:{1}#</span>',
 
        _refresh: function() {
            var that = this;
            var template = kendo.template(kendo.format(that._template, that.options.infoIcon, that.options.text));
            //How can I find the viewModel the body is bound to??????
            //$(that.element).html(template(viewModel));
        }
    });
 
    ui.plugin(InfoBox);
 
})(jQuery);

The issue I am facing is how can I access the viewModel the body of the page is bound to from within my custom widget?

3 Answers, 1 is accepted

Sort by
0
Jack
Top achievements
Rank 2
Iron
answered on 19 Sep 2012, 10:49 AM
I have painfully got it working but a code review would be helpful. See http://jsfiddle.net/JWT6g/

  1. I could not get it to work with data-bind="source:xxxxxxx". I had to use data-source="xxxxxxxx" although Widgets seem to support data-bind (see http://demos.kendoui.com/web/mvvm/widgets.html). When using data-bind, you get that.options.source as a string and there is not much you can do with it;
  2. When you use the data-source attribute, that.options.source is still a string and you have to initialise that.options.dataSource to actually get an observable;
  3. Actually this is not sufficient. kendo.bind calls kendo.initWidget which does
if (dataSource) {
    if (typeof dataSource === STRING) {
        options.dataSource = kendo.getter(dataSource)(window);
    } else {
        options.dataSource = dataSource;
    }
}
kendo.getter requires that the viewModel be a global variable (kendo.getter(dataSource)(window) 
returns window[dataSource]), this is why you have in the fiddle above:
var viewModel = window.viewModel = kendo.observable({...}).

Then there are other issues:
  • When should you be using data-bind attrribute against data-source attribute + data-custom attributes?
  • How should you use that.options.autoBind? What's the purpose?
  • How would you build the mobile version of this widget?
  • What is kendo.notify() which appears requently in kendo widget source code?
  • The kendo template does not seem very useful in this case, does it? We might as well generate plain html as any change to the dataSource always calls refresh. The idea with the template was to rely on its ability to sync with the dataSource, but since our widget needs to reference the dataSource to initiate the template, it might as well do the job by implementing a change event handler, but in this case are we really MVVM? 
There is very little documentation. Am I doing this properly?
0
Jonas
Top achievements
Rank 1
answered on 16 Apr 2013, 07:00 AM
Thank you for your question and solution. I'm about to use the custom widget with an observableobject aswell, but the lack of response from the kendo team here makes me hesitate. Is this simply not a recommended method? I use custom widget because it seem  to provide a kendo supported structure for building components, but perhaps it's not the best choice?
0
Jack
Top achievements
Rank 2
Iron
answered on 22 Apr 2013, 02:59 PM
Telerik have confirmed that they would not support the development of custom widgets and they have referred me to Telerik professional services (subject to additional fees). So despite having a commercial license, I did not get any response to my requests regarding custom widgets. For this reason, I am still keeping an eye on the progresses of the Wijmo framework which is based on jQuery UI and knockoutJS and which now provides mobile components.

As far as "recommended method" and "best choice" are concerned, I could not advise you but it seems pretty obvious to me that (1) any big project would require custom widgets that access a complex shared view model, (2) any complex shared view model is necessarily non-tabular, and (3) the options to implement both with the kendo UI framework are limited.
Tags
MVVM
Asked by
Jack
Top achievements
Rank 2
Iron
Answers by
Jack
Top achievements
Rank 2
Iron
Jonas
Top achievements
Rank 1
Share this question
or