Rashim's Blog

Archive for the ‘WinJS’ Category


We usually need to develop some independent controls when we work in web or in other platform as well. This time I am going to introduce how to develop your own dropdown. We can easily use built in HTML select control but in some cases it might not fulfill our business requirements. Recently I have been working in windows 8 app where there is in need to develop a custom drop down for some of its business requirement. So I would like to share you today how to develop a custom dropdown or another controls that you would like to develop using WInJS, Html and Knockout and how to bridge those three technologies in a single hub.

If you are familiar with knockout you definitely know about how to develop custom components or if you are working with angular then you can guess it like a directive since knockout component’s is pretty much same with Angular directive. As my thought goes to use knockout, I took initiatives to develop a custom components in knockout. Here I have used using WinJS from what  I have got the flavor of OOP. But I could use raw Javascript but in this case I need to do some extra work should I want to have the taste of class based coding. Let’s move to code,

First the template that I have used for this custom drop down,

<div>
    <button class="dropdown_container" id="btnDropDown" data-bind="click:handleDropDown.bind($data)">
        <div data-bind="with: selectedItem">
            <span data-bind="text:title"></span>
        </div>
    </button>
    <div class="dropdown_bottom_frame" id="dropDownFlyout" data-win-control="WinJS.UI.Flyout" data-win-options="{ _sticky: false}">
        <div data-bind="foreach:items">
            <div data-bind="template: {name:$parent.itemTemplate}"></div>
        </div>
    </div>
</div>

There is nothing to explain about this template code since this is pretty straight forward. Here I have used WinJS Flyout for drop down and the data for this control has been bind from its controller.

The controller,

(function () {
    var dropdownController = WinJS.Class.define(function(params, element) {
        var self = this;
        var flyout = document.getElementById("dropDownFlyout");
        var anchor = document.getElementById("btnDropDown");
        this.items = params.items;
        this.selectedItem = params.selectedItem;
        this.isOpen = ko.observable(false);
        this.itemTemplate = params.itemTemplate;
        this.isOpen.subscribe(function(newValue) {
            if (newValue) {
                flyout.winControl.show(anchor, "bottom", "center");
            } else {
                flyout.winControl.hide();
            }
        });

        flyout.addEventListener("afterhide", function() {
            self.isOpen(false);
        });

        WinJS.UI.processAll().done();
    }, {
        handleDropDown: function() {
            this.isOpen(!this.isOpen());
        },
        selectItem: function(item) {
            this.selectedItem(item);
            this.handleDropDown();
        }
    }, null);
    WinJS.Namespace.define("Rashim.RND.Controls", {
        DropdownController: dropdownController        
    });
})();

In that code I have just taken the flyout control and manually drop and down it through code. Some functions have been given here to handle for its selection mode and passing data to its consumer. Through the params I have got the collections and selected item object so that I could propagate selected Item to the consumer.

And this is the component definition which define its ViewModel and template,

define(['text!./dropdownView.html'], function (htmlTemplate) {
    var viewModel = Rashim.RND.Controls.DropdownController;
    return {
        viewModel: {
            createViewModel: function (params, componentInfo) {
                return new viewModel(params, componentInfo.element);
            }
        },
        template: htmlTemplate
    };
});

I have used here require JS for lazy loading and text is an AMD loader for require to load text resource in my case which is template.

That’s it, Now the consumer consume it on it’s in any dom inside,

<dropdown params="{items:items,selectedItem:selectedItem,itemTemplate:'dropdown-template'}"></dropdown>

Here Items and selected item are the observable property of the ViewModel of the consumer and the control will get those through its params.

Enjoy!!! Source code is available here

Advertisements

%d bloggers like this: