Monday, 21 July 2014

k2 Custom SmartControl: Client Side

This is a continuation of the previous three posts:

To set up a k2 Custom Control Visual Studio project click here.
To set up the xml definition click here.
To set up the server side class click here.

if you have these three complete continue on.

Picking up where we left off we have to make one last modification, recall that we added a reference to our javascript file in the AssemblyInfromation.cs class, but we still have to add our JavaScript to the rendered page in the Constructor of our Custom Control. so lets do that:

public MySmartControl()
    : base()
{
    //Define the javascript key and path
    string jsKey = "MyCustomControls_MySmartControl_MySmartControl_Script";
    string jsUrl = "MyCustomControls.MySmartControl.MySmartControl_Script.js";

    // add the script to the designer environment
    this.DesignCodePaths.Add(jsKey, jsUrl);

    // add the script to the runtime environment
    this.CodePaths.Add(jsKey, jsUrl);
}

now we can focus on JavaScript, so lets add functions to get our control, set and get both the value and properties. First we'll start with an empty self calling function that builds our javascript object

// self calling function, will fire itself when rendered
(function ($, undefined) {

    //check if MyCustomControls object exists, if not create it
    if (typeof MyCustomControls === "undefined" || MyCustomControls === null)
        MyCustomControls = {};

        //add MySmartControl object to MyCustomControls object
        MyCustomControls.MySmartControl = {
        
        //TODO add interaction logic between control and xml definition 
      
        };
}(jQuery));


with this ready now we have to implement all the endpoints we defined in our XML Definition, namely

  • get/setValue
  • get/setProperty
  • events

// self calling function, will fire itself when rendered
(function ($, undefined) {

    //check if MyCustomControls object exists, if not create it
    if (typeof MyCustomControls === "undefined" || MyCustomControls === null)
        MyCustomControls = {};

        //add MySmartControl object to MyCustomControls object
        MyCustomControls.MySmartControl = {

            // Custom function to retrieve html rendering of control, it is marked
            // with an underscore to emphesize that it is a private function that is
            // not declared in the xml definition
            _getControl: function (objInfo)
            {
                return document.getElementById(objInfo.CurrentControlId);
            },

            // getValue function defined in xml Definition
            getValue: function (objInfo) {
                var control = MyCustomControls.MySmartControl._getControl(objInfo);
                return control.innerHTML;
            },

            // setValue method defined in xml Definition
            setValue: function (objInfo) {
                var control = MyCustomControls.MySmartControl._getControl(objInfo);
                control.innerHTML = objInfo.Value;
            },

            // getProperty method defined in xml Definition, retrieves property
            // that is saved as attribute on the root container of the control
            getProperty: function (objInfo) {
                var control = MyCustomControls.MySmartControl._getControl(objInfo);
         
                if (control.hasAttribute(objInfo.property))
                    return control.getAttribute(objInfo.property);
                return control.getAttribute("data-{0}".format(objInfo.property));
            },

            // setProperty method defined in xml Definition, sets an attribute on
            // the root element of the control to the property value
            setProperty: function (objInfo) {
                var control = MyCustomControls.MySmartControl._getControl(objInfo);

                if (control.hasAttribute(objInfo.property))
                    return control.setAttribute(objInfo.property, objInfo.Value);
                control.setAttribute("data-{0}".format(objInfo.property), objInfo.Value);
            },

            // excute is defined in the xml Definition, it is responsible for handling
            // all incomeing method calls that are defined in the xml definition and called
            // from the k2 rules.
            execute: function (objInfo) {
                var parameters = objInfo.methodParameters;
                var method = objInfo.methodName;

                switch (method) {
                    case "ShowAlert":
                        alert(parameters.message);
                        return;
                    case "Add":
                        return (parameters.double ? 2 : 1) *
                               (parseInt(parameters.addendone) + parseInt(parameters.addendtwo));
                }
            }
        };

}(jQuery));

now with that complete we have to add the logic to pass on the events from the control to k2

$().ready(function () {
    $(document).delegate('.MyCustomControls-MySmartControl', 'click.Control', function (e)
    {
        console.log(this.id); //Notice that this.id = CurrentControlId

        // raiseEvent is an internal k2 fucntion in the events.js file that will pass the
        // event to the k2 rules and fire the event on the appropriate instance of the control
        raiseEvent(this.id, 'Control', 'OnClick');
    });

});

To recap: Think of your basic control as a three file beast:

  • Xml Definition: used to define all the properties, methods, events and supporting functions your control will have. The properties are mapped to the server side .cs file for serialization, but the methods, events and supporting functions are defined in the client side .js file.
  • Server side: used to de/serialize all the properties defined in your control, also to render the control initially on the page in the RenderControl method.
  • Client side: the meat of the control, this is where the interaction between the user and k2 environment occurs, events let users execute k2 rules and methods let k2 rules execute functions defined in the client side of your control.