Drag and Drop with LightSwitch HTML Client (Rohit Agrawal)

Drag and Drop with LightSwitch HTML Client (Rohit Agrawal)

Rate This
  • Comments 25

While the built-in controls and features provided by LightSwitch are optimized for smaller form factors, it is possible to take advantage of the mouse events available on desktop browsers to enable drag and drop when then situation calls for it. With HTML5 it is possible to grab an object with a mouse click from one location and drop it into another. This feature can be useful in LightSwitch applications where you display lists based on a property with some choice list values. A To-Do list or a scheduler type of application are good examples. The following post will demonstrate one way you can use HTML5 drag and drop in your apps. If you are not already familiar with LightSwitch, please see LightSwitch HTML Client Documentation and LightSwitch HTML Client Tutorial.

Create a Tasks (To-Do) Application

First, let’s start by creating a new LightSwitch HTML application and add a Table called Task with the following properties – ‘Name’ of type String and ‘State’ of type String. Add a choice list to the property ‘State’ with values – ‘Not Started’, ‘In Progress’ and ‘Completed’. Later in the application, we will be filtering Tasks based on their state.

1

Add 3 server queries – TasksNotStarted, TasksInProgress and TasksCompleted. The TasksNotStarted query will have the following filter – “Where State = <Literal> Not Started”. Likewise, TasksInProgress and TasksCompleted will have the following filters respectively - “Where State = <Literal> In Progress” and “Where State = <Literal> Completed”.

TasksNotStartedQuery

Add a Browse screen called ‘Home’ with Screen data as ‘None’ and change the control type of ‘Group’ Tab from ‘Rows Layout’ to ‘Columns Layout’. Now add all 3 queries to the Home screen by selecting “Add Data Item” button at the top of the screen designer and then drag them over into the content tree. Lastly add a command bar button on Home screen to add new Task. This is how the ‘Home’ screen will look like.

2

Now that we have 3 lists on our Home screen, it will be hard to distinguish between them if we do not show the headers for each list. So let’s now check off the ‘Show Header’ property for each list.

ShowHeader

Make List Items Draggable

On ‘Home’ screen, select ‘TasksNotStartedTemplate’ (Note: The display name of TasksNotStartedTemplate is ‘Task’) and click ‘Edit PostRender Code’ on the property sheet.

3

First, copy the following method and paste it on the Home.lsml.js file. ‘draggable’ is an HTML attribute which is by default set to false. For each list item, we will be setting this attribute to true. Moreover, we will also be passing the TaskId along with each list item that is being dragged so that later when we drop a task into another list we know which task’s state has to be changed.

function makeDraggable(element, taskId) {
    //Get the entire list item
    var listItem = $(element).closest("li");

    //Enable draggable feature
    listItem.attr("draggable", true);

    //Pass taskId along with the listItem when it is being dragged
    listItem[0].ondragstart = function (e) {
        e.dataTransfer.setData("Text", taskId.toString());
    };
}

 

Now, copy/paste the following code in TasksNotStartedTemplate_postRender() method.

myapp.Home.TasksNotStartedTemplate_postRender = function (element, contentItem) {
    // Write code here.
    makeDraggable(element, contentItem.value.Id);
};

 

Similarly, add following code to TasksInProgressTemplate_postRender() and TasksCompletedTemplate_postRender() methods.

myapp.Home.TasksInProgressTemplate_postRender = function (element, contentItem) {
    // Write code here.
    makeDraggable(element, contentItem.value.Id);
};
myapp.Home.TasksCompletedTemplate_postRender = function (element, contentItem) {
    // Write code here.
    makeDraggable(element, contentItem.value.Id);
};

On pressing F5, you will be able to drag a list item but will not be able to drop the list item yet.

4

Enable Dropping of List Items

To allow a list item to be dropped into another list we will have to prevent the default handling of all 3 lists which can be done by calling the event.preventDefault() method. The ondrop event will essentially get the taskId of the Task that is being dropped, change the state of task, save changes and eventually refresh all 3 lists. Open the Home.lsml.js file and copy/paste the following method at the bottom.

function enableDrop(element, stateType, screen) {
    var ulElement = $(element).find("ul").closest("div");
    ulElement[0].ondragover = function (e) {
        e.preventDefault();
    };
    ulElement[0].ondrop = function (e) {
        //Get TaskId
        var data = e.dataTransfer.getData("Text");
        var filter = "Id eq " + data;
        myapp.activeDataWorkspace.ApplicationData.Tasks.filter(filter).
            execute().then(function (result) {
            //Change state of Task
            result.results[0].State = stateType;
            return myapp.activeDataWorkspace.ApplicationData.saveChanges();
        }).then(function () {
            //Refresh all 3 lists
            screen.TasksNotStarted.refresh();
            screen.TasksInProgress.refresh();
            screen.TasksCompleted.refresh();
        });
    }
}

Now add postRender code to all 3 Lists – TasksNotStarted, TasksInProgress and TasksCompleted.

myapp.Home.TasksNotStarted_postRender = function (element, contentItem) {
    // Write code here.
    enableDrop(element, "Not Started", contentItem.screen);
};

myapp.Home.TasksInProgress_postRender = function (element, contentItem) {
    enableDrop(element, "In Progress", contentItem.screen);
};

myapp.Home.TasksCompleted_postRender = function (element, contentItem) {
    enableDrop(element, "Completed", contentItem.screen);
};

You should now be able to drag a list item from one list and drop it into another. On dropping a Task to another list, the status of the dragged Task will automatically change and all 3 lists will refresh.

Add Background Color to Lists

Since the background color of all lists is white by default, it might be hard for the user to see a spot to drop a task. This problem can be solved by simply adding different background colors to all 3 lists via CSS. Here’s one way you can do this. Add the following highlighted line of code to the PostRender methods of all 3 lists. If we change the background color of entire list then it would change the background color of list header as well and since a list header is not a droppable region, we will first find the element on which a list item can be dropped and then change the background color of this element.

myapp.Home.TasksNotStarted_postRender = function (element, contentItem) {
    // Write code here.
    $(element).find("ul").closest("div").css("background", "#FFB6C1");
    enableDrop(element, "Not Started", contentItem.screen);
};

myapp.Home.TasksInProgress_postRender = function (element, contentItem) {
    $(element).find("ul").closest("div").css("background", "#FFE4B5");
    enableDrop(element, "In Progress", contentItem.screen);
};

myapp.Home.TasksCompleted_postRender = function (element, contentItem) {
    $(element).find("ul").closest("div").css("background", "#90EE90");
    enableDrop(element, "Completed", contentItem.screen);
};

This is what the screen will look like.

5

Increase Area of the Droppable Region

The droppable region on a list is currently limited to the number of list items within a list. You might want to increase it in order to make full utilization of the screen space. The droppable region’s area can be increased by making the lists taller so that each list grows in height leaving the height of a list item unaffected. On ‘Home’ screen, select ‘Columns Layout – Group (Tab)’ and on the property sheet set the height to ‘Stretch to Container’. Similarly set the height of all 3 Lists to ‘Stretch to container’.

6

This is what the screen looks like after making the above changes. The list item can now be dropped anywhere on the colored portion of the list.

7

Conclusion

With LightSwitch it is possible to add various HTML5 features and enhance the experience of your web application by writing custom code. Anything you can do in JavaScript & HTML5 you can do in the LightSwitch HTML client. The LightSwitch HTML client is available in Visual Studio 2012 Update 2 and higher but I encourage you to download Visual Studio 2013 RC and try out all of our new features!

And for a tutorial on HTML5 Drag & Drop, see HTML5 Drag and Drop.

- Rohit Agrawal, SDET, LightSwitch Team

Leave a Comment
  • Please add 8 and 7 and type the answer here:
  • Post
  • Wow, nice :) "Anything you can do in JavaScript & HTML5 you can do in the LightSwitch HTML client" !!

  • Awesome !!!

  • Nice.  Is there documentation on list methods like .load() vs. .refresh()?

  • This is a very nice and extremely useful article! Thanks for sharing.

  • Even *I* could understand this, lol. Thanks Rohit!

  • Why is this nice??

    we live in 2013!! and Drag & Drop should be standard without writing so much (ugly) Javascript code!

    all the hype with HTML5 is really a joke - you cannot build real LOB's and the apps for mobile devices are "Micky Mouse" apps...

    with the LS HTML client and that much Javascript code it isn't realy RAD - MS should make a view to other better technologys like e.g APEX which can also produce mobile HTML5 apps and good desktop apps and is very flexible and should not building new development environments from scratch!

    robert

  • This is nice, HTML5 & LightSwitch is more flexible. More JavaScript code generation will come. Really great stuff! I have applied this to some demo apps. This is VS2013 and uses "<query>.refresh" is there any comparable way to get the refresh working in VS2012? Apart from that it works in VS2012 ok.

  • This is a great post.

    Now I need to re-think my apps to see how this could be used.

  • On the day that the HTML client achieve what silverlight already do, maybe I'll use it

    :)

  • @Dave - On VS2012 replace "screen.<query>.refresh()" with "screen.<query>.load()". This will also update the lists.

  • I had already implemented drag and drop on one of my lightswitch app but I got to say that the trick of the bigger area is the good one that I'm impatient to try! :-)

  • Hi

      You haveany queries visit www.kbreducation.com

  • Wish this would work on an iPad.  It works on Surface and Surface Pro, though.

  • Finally found a way to fix this for iPad functionality.  TimRuffles made a shim script on GitHub called ios-drag-drop.js that makes iOS work with the HTML5 "draggable" attribute as it should without having to add jQuery UI or touchpunch (neither of which I ever got to work.) Just copy the script to your Scripts directory, and add a reference to it in your default.html file, and this example will properly work on an iPad.  Works on Android, too.  The only thing I haven't been able to figure out is why the z-order of the items is under the drop targets instead of on top of them, but that's mostly a cosmetic issue for me.  Here's the link:

    github.com/.../ios-html5-drag-drop-shim

  • Hi Rohit, nice article!

    When drop I need to know when the item is dropped (first in destination list, middle or at end). How I know where the item is dropped in the new list?

    Thanks in advance,

Page 1 of 2 (25 items) 12