Tag Archives: winjs101

Using WinJS.Binding.List to update the list view

Published December 3, 2013 1:06 pm

WinJS.UI.ListView is the most used control in WinJS library. At the beginning, you typically start with static List views. In such List Views, data does not change after it is bound. You may have to sort or group data which can be achieved using createSorted or createGrouped methods on List. You can order the items, group the items, and order the groups using these methods. If you follow some of the msdn listview samples, it is sort of clear. (Note: not all samples needs to be followed to get hang of list view. Some of them like custom data source, incremental loading are advanced scenarios).

When you working with dynamic data, list view updates as user interacts with the list view. Examples:

  1. User can right click a item, and delete it using contextual app bar command.
  2. User clicks/taps an item. The item is either removed or updated.

List view elements sort order and grouping needs to be maintained after the item change or list changes. In this post, let’s look into (2). I will try to cover (1) in another post. To go over this, let’s take a simple problem of displaying list of todo tasks.

  1. The tasks should be displayed in two  groups – ‘todo’ and ‘done’ groups.
  2. When a task is clicked or tapped in the todo group – it is moved to ‘done’ group.
  3. ‘done’ group should maintain only the latest 5 done tasks. oldest task gets off the list when list grows beyond 5 tasks.

my-tasks-1With this, Let’s look at the HTML

<div id="todoListView" data-win-control="WinJS.UI.ListView"
    data-win-bind="winControl.itemDataSource: items.dataSource; winControl.groupDataSource: items.groups.dataSource"
    data-win-options="{
      itemTemplate: select('#todoItemTemplate'),
      groupHeaderTemplate: select('#groupHeaderTemplate'),
      selectionMode: 'none', swipeBehavior: 'none', tapBehavior: 'invokeOnly' }">
</div>
  1. list should have tapBehavior set to invokeOnly to enable click/tap.
  2. itemTemplate and groupHeaderTemplate are set which is kind of obvious.
  3. this snippet binds itemDataSource and groupDataSource in html. If you don’t have view model (MVVM) separate in your code, you may set it in the .js file.

Let’s look at the sample data.

var data = [
    { status: 'todo', title: 'wake up' },
    { status: 'todo', title: 'brush your teeth' },
    { status: 'todo', title: 'take bath' },
    { status: 'todo', title: 'do yoga' },
    { status: 'todo', title: 'take breakfast' },
    { status: 'todo', title: 'check email' },
    { status: 'todo', title: 'check facebook' },
    { status: 'todo', title: 'check stackoverflow forum' },
];

We will sort the list using the sort key <status, finishTime>. finishTime will be added whenever user taps the item. todo status is sorted before done status. finishTime is sorted in descending order. This way – all done items are order towards end of the list. Further, If any item is to be dropped, it is at the end of the list.

 

    function compareStatus(t1, t2)
    {
        if (t1 == t2)
            return 0;
        else if (t1 == 'todo')
            return -1;
        else
            return 1;
    }

    function compareFinishTime(d1, d2)
    {
        if (d1 == undefined && d2 == undefined)
            return 0;
        // treat unfinished task ahead in sort order
        else if (d1 == undefined)
            return -1;
        else if (d2 == undefined)
            return 1;
        else
        {
            var t1 = d1.getTime(), t2 = d2.getTime();
            // treat recently finished task ahead in sort order
            if (t1 > t2)
                return -1;
            else
                return 1;
        }
    }

    var sortedList = list.createSorted(function compare(i1, i2)
    {
        var c1 = compareStatus(i1.status, i2.status);
        if (c1 != 0)
            return c1;
        var c2 = compareFinishTime(i1.finishTime, i2.finishTime);
        return c2;
    });

Further, we use createGrouped to group the sorted items and order the groups.

    this.items = sortedList.createGrouped(function groupKey(item)
    {
        return item.status;
    },
    function groupData(item)
    {
        return { title: item.status };
    }, 
    function groupSorter(g1, g2)
    {
        // keep todo items group b4 'done' items group
        if (g1 == g2)
            return 0;
        else if (g1 == 'todo')
            return -1;
        else 
            return 1;
    });

Now, to move the item from ‘todo’ group to ‘done’ group – we can change the item in the iteminvoked handler and notify the list for item mutation using notifyMutated method. Once notified, list sorted and grouped projection will update themselves. It will reflect in the bound list view.

 
registerItemInvokedHandler: function registerItemInvokedHandler()
{
    function oniteminvoked(event)
    {
        var index = event.detail.itemIndex;
        var item = this.viewModel.items.getAt(index);
        // click on 'done' tasks should be noop. 
        if (item.status == 'done')
            return;
        item.status = 'done';
        item.finishTime = new Date();
        this.viewModel.items.notifyMutated(index);
        // schedule removal for later using setImmediate
        WinJS.Promise.timeout().then(removeIfReqd.bind(this));
    }

    function removeIfReqd()
    {
        var count = 0;
        var items = this.viewModel.items;
        for (var i = items.length; i > 0; i--)
        {
            var item = items.getAt(i - 1);
            if (item.status == 'todo')
                break;
            count++;
        }

        // remove only if more than 5 'done' items
        if (count > 5)
            items.splice(items.length - 1, 1);
    }

    todoListView.addEventListener('iteminvoked', oniteminvoked.bind(this));
},

my-tasks-3* Note the code above references items from the viewModel. That needs to be modified to reference items as per your code.

This way – we saw in this post – how createSorted, createGrouped along with notifyMutated – can be used to build a dynamic list view.

WinJS 101

Published September 25, 2013 1:47 pm

Last couple of months has been heads down into our next app; The app is more involved app with authentication, backend service etc. I have not been able to find time to write blog. Today, I thought of resurrecting again. Here is what we are going to do. We will go over WinJS over next set of posts – as a winjs 101 for developer.

WinJS 101 for developer will be as close to code as possible. It is not meant to be executive summary. It is meant to be developer summary; a dev to dev talk/share – to help you jump start on this. If you are developer, who is starting because a) your current project needs it b) you want to remain updated of windows app development c) you want to get on to html/css/javascript since they are open and skill will be valuable on other platforms. It is likely that the post might help you. At the very least, it is an attempt with that intent. Let’s get started.

winjs-lib-002What is WinJS – well, it is windows javascript library. Like you have underscore.js, backbone.js – various javascript libraries, it is a javascript library meant for developing windows modern (aka metro) applications. When you open a new winjs based windows store application project in VS express 2012, you will find reference to winjs lib in solution explorer – like you used to find default reference to few net assemblies e.g. system in your .net projects. Your curiosity will certainly expand the node and you will find couple of these files there.

ui-dark.css/ui-light.css : css provides the way to declaratively style a html web page. css is available to style winjs applications. This file contains the default style rules for the windows controls. MSDN documentation of the WinJS controls will document the css classes that can be used to style them. For example – refer styling of listview control here. Typical web developer will not need introduction to css. If you are not a typical web developer, css introduction here helped me in past. Do not try to go through this file at beginning, it might be intimidating. It is like seeing disassembly of a .net assembly. Ctrl+f in this file will be of most help during first few days when documentation does not help getting to css classes for a winjs control.

base.js: In simply terms, this is the non-ui part of the winjs lib. Winjs library provides basic functions like WinJS.Class.define/derive: to define a class (using javascript prototype underneath), WinJS.Namespace.define: to organize code in namespaces (using simply dynamic javascript  object underneath) albeit there is no native thing called namespace in javascript, WinJS.Binding.List: one of the first class that you will get exposed; it is used as dataSource for winjs controls like ListView and FlipView, WinJS.Application namespace: apis/events for app start/suspend, session and setting mgmt. you will see reference to this mostly in default.js in your project. Note: that winrt apis* are natively accessible to winjs application and not part of the winjs lib. WinJS library provides added functionality to support winjs based application development. For winrt apis example: refer Windows.Storage.FileIO: it provides apis to read/write files. For all windows(aka winrt) api for all windows store apps – refer here. These can be used in windows store app written in javascript or any other supported language like c#, c++ etc.

*winrt api: winrt apis are referred as windows apis that are available to a windows store app, written any language of choice – c#, javascript, c++ etc. It is not a new/latest version of .net frameworks. It is a new framework altogether meant for windows store (modern) app development. This is a one line intro to winrt which is a longer  discussion otherwise.

ui.js: this is the ui part of the wijs lib. All html 5 controls (rather all documented to be supported by IE) can be used in winjs app. There are subtle differences in support when used in native modern app vs IE. At meta level, you can think of using html/DOM to build UI without getting into details at the onset. If you are web developer, you get to leverage all your knowledge of native html controls; listing of all controls here will make you happy.

ui.js provides additional ui controls apart from native html – like ListView, FlipView and more. There controls are rendered below a html div, written in javascript and styled using css. Not sure what that means – use debug->windows->DOM Explorer->select element in VS, and explore the html/css below a list view in your application. you will find that WinJS ListView control renders itself by spitting html in the DOM.

There is lot more under WinJS.UI namespace. Many of the controls like HubControl, SearchBox are coming windows 8.1. ListView, DatePicker, TimePicker, Flyout, AppBar has been the frequently used controls in my case. Again, like in case of base.js – this is not all. All other windows (aka winrt) controls – like Windows.UI.Popups.MessageDialog – are available to javascript and other languages like c#, c++.

Going back to our winjs lib node in picture above, you will find string resource files below en-us node. ui-dark and ui-light.css provides different style for light and dark theme. your application will use only one of them.

we have not yet finished talking about the other files in the a typical winjs project. There will be other things like data-win-control, data-win-options in html that won’t look like html attributes; a typical page in winjs app will be a Winjs PageControl defined using WinJS.UI.Pages.define(); javascript for the page needs to be organized little differently than its done for typical web pages. We will talk about these next time.

Before we close on this: Why WinJS? You will the right person to make the choice for your project. I will share few of my observations:

  1.  Are you a web developer that have sound html/css/js skills and need to code a windows store app? WinJS based application development will surely help to leverage your skills. At the same time, do not think you can get around without  any additional learning curve. There are windows specific nuances. but again, you will certainly have better jumpstart here than in going with c# and xaml.
  2. Are you are developer that have sound c#, xaml skills? yes – then certainly, windows provides default path of using xaml & c#. That will align well and give you good jumpstart. Should you think even once of learning html/js/css way of building the windows store app? Ask yourself do you want to get exposed to html/js/css. These skills are likely more transferable to other web/mobile development platforms. They might help you in the long run and good to have these skills in your arsenal even if you are a old timer solid dev. At the same time, do expect a learning curve of 6 month even if you are a Pro in c#, xaml, ms technologies; this is assuming that you have no exposure to css/html/js.
  3. If you already have sound html/css/js knowledge – using this library do help for windows store app dev.
  4. html/css/js skills are transferable to other web/mobile platforms. This will also come with disclaimer that winjs apis or windows api knowledge development will be key and require investment of time. This knowledge won’t be directly transferable to other platforms.
  5. if you are building application that falls in integration category – what I mean, the application falls in category of building a native windows experience for one or more web services. json/ajax- provide a loose / lightweight way to interact with services; winjs might help.
  6. does your application have lot of algorithmic, complex logic implementation? javascript is a dynamic language and not strongly typed. The benefits of compiler catching your common coding mistakes will not be there. For example – even if you invoke a method without passing required number of arguments, code will not give error until executed. Now, think of complex product code base, making changes and handling regression. This is flip side of js that I have experienced. but decided to live with it. The power of language needs to be used with caution.
  7. for a specific project, you may want to pilot to verify that framework suffices your needs. There is certainly difference in controls available in xaml vs winjs.
  8. winjs won’t provide two way binding by default. I wrote a naïve two way binding impl. sufficient enough for our current needs.
  9. in sum total, I would say staying with html/css/js stack was the biggest motivator to stay with winjs.