LightSwitch 2013 HTML Client – Easily add Multi Item Selection to your Lists and Tables!

Enhancing your LightSwitch List, Tiles and Table controls – Updated!

We have refactored from the earlier build… so please review the new steps!

TableWithPersist
CustomersLimit4

As of May 2014, Out of the Box LightSwitch list, tiles and table controls only allow for selection of a single item.

Until now!

The demo/test drive has been updated showing the new upcoming functionality check it out: MultiSelect Preview

So… we’re like squirrels here, constantly distracted. And so with that said, we’ve nailed down our long term name for the library. Going forward we’ll be branding as LightSwitch Wires, or lsWires for short. Since in reality that’s kind of what we all do. We add the wiring to LightSwitch to make things work or work better. And this naming convention works for our other disciplines like Kendo UI and Syncfusion. We’ll keep the “Wires” branding and just swap out the prefix for the type of wires we’re providing. Thanks for your patience, this is the LAST breaking change.

Now on with it… Within the lsWires library we've provided the functionality to enhance the list and table controls

  • Selection of multiple items
  • Ability to limit the number of selections
  • Select/Unselect all items
  • Get the selected item count
  • Retrieve the data of the selected items
  • Persist selections for the session
  • We no longer take over the ItemTap
  • Multiple lists can be on the same screen
  • Same code base works across all 3 control types

Sounds awesome eh? So lets get started on how to implement this new functionality…

  1. Create a new LightSwitch 2013 HTML Application
  2. Lets name it: itgLsMultiSelect
  3. When at the Start with data screen, click on Attach to external…
  4. Data Source Type: OData Service
  5. OData service endpoint:
    http://services.odata.org/northwind/northwind.svc/
  6. Authentication type: None
  7. Choose the following entities:
    Customer
    Employee
    Product
  8. Name the data source: Northwind
  9. Click the finish button
  10. Close any open editor windows
  11. Save your solution
  12. Over in your your Solution Explorer pain
  13. Add the following NuGet package to the HTML Client project
    lo-dash.js
  14. From our GitHub repository
    Add lsWires.js to your Scripts folder
    Add lsWires.css to your Content folder
  15. Now open up your default.htm file in the client project
  16. Add lo-dash.js followed by lsWires.js to the scripts section
  17. Add the lsWires.css as the last stylesheet
  18. Right click on the Screens folder, select Add Screen…
  19. Select Browse Data Screen
  20. Screen Data: Northwind.Customers
  21. Click ok
  22. Save your solution, run the application
  23. Go ahead and click on items, notice single selection
  24. Stop your application
  25. Click on the Tile List, Customers
  26. Click on Edit PostRender Code in the properties window
  27. To get intellisense, drag from solution explorer the file lsWires.js onto your page
  28. Now we only need ONE line of code to enable multi-select
    // Enable multi-item selection on this tile control
    lsWire.list.enableMultiSelect(contentItem);
    
  29. Before you can run, remove the default ItemTap that LightSwitch automatically adds for the list. We did not create the view screen that the ItemTap is expecting so you’ll get an error when selecting if you don’t.
  30. Save your solution, run your app
  31. BOOM! Multi-Select enabled!
  32. You can also unselect by clicking a selected item
  33. Hmmmm… how do I get the data of the selected items?
  34. Stop your application
  35. Under the Customer List Tab, add a new Group
  36. Move it right under the Command Bar
  37. Change the type to be a Columns Layout
  38. Then add 3 more Rows Layout under the columns layout
  39. For all 3 change the width setting to Fit to Content
  40. Add a new Button into the first rows layout
  41. Select Write my own method, name it: GetSelected
  42. Double click the button to edit the code
  43. We're going to add a few lines
    Get the list contentItem
    Call our method to get the data, which returns an array of entities
    Then we'll display the data
    var list = screen.findContentItem("Customers");
    var count = lsWire.list.selectedCount(list);
    var selected = lsWire.list.selected(list);
    var text = "Customers Selected\n\n";
    _.forEach(selected, function(item) {
          text += item.CustomerID + " - " + item.CompanyName + "\n";
    });
    text += "\n\nCount = " + count;
    window.alert(text);
    
  44. Save and run your application
  45. Select a few items, click on Get Selected
  46. Unselect a few, Get Selected, only selected get returned
  47. Ok lets continue going thru adding functionality
  48. Add two local properties, boolean
  49. Name them SelectAll and SetLimits
  50. Drag the SelectAll under the second Rows Layout
  51. Change the control type to be of a Custom Control
  52. Over in the properties window, set the label position to None
  53. Then click on Edit Render Code and add the following
    	// Render a checkbox
    	lsWire.checkbox.render(element, contentItem);
    
    	// When the checkbox changes state, either select all or not
    	contentItem.dataBind("screen.SelectAll", function (newValue) {
    		if (newValue != undefined) {
    			var list = contentItem.screen.findContentItem("Customers");
    			lsWire.list.selectAll(list, newValue);
    		}
    	});
    
  54. Now drag the SetLimits property under your 3rd Rows Layout
  55. Change the control type to be of a Custom Control
  56. Change its Display Name to: Limit of 4
  57. Change the label position to None
  58. Then click on Edit Render Code and add the following for this one, its a bit more lengthy as we’re adding in some cool features
    	// Render our checkbox
    	lsWire.checkbox.render(element, contentItem);
    
    	// When the checkbox changes state, set or remove our limits
    	contentItem.dataBind("screen.SetLimits", function (newValue) {
    		
    		if (newValue !== undefined) {
    
    			// Our dependent item
    			var selectAll = contentItem.screen.findContentItem("SelectAll");
    
    			// Get our list
    			var list = contentItem.screen.findContentItem("Customers");
    
    			// Current count of selected items
    			var count = lsWire.list.selectedCount(list);
    
    			// If the checkbox is selected, limit to 4 items
    			if (newValue != undefined && newValue === true) {
    
    				// Set our limit, returns the limit count
    				var ttl = lsWire.list.totalSelectionsAllowed(list, 4);
    
    				// if select all was set, checked
    				if (selectAll.value === true)
    
    					// set the property to false, dataBinding will do the rest
    					contentItem.screen.SelectAll = false;
    
    				// Else is the current count greater than our limit?
    				else if (count > ttl) {
    
    					// Count is greater, so unselect all items
    					lsWire.list.selectAll(list, false);
    				}
    
    				// Since we are limiting, disable the select all checkbox
    				selectAll.isEnabled = false;
    			} else {
    
    				// Limit was unselected, renable select all and remove limits
    				selectAll.isEnabled = true;
    				lsWire.list.totalSelectionsAllowed(list, null);
    			}
    		}
    	});
    
    
  59. Its that easy!
  60. Save and run your application
  61. Toggle your limits
  62. Select your 4 items, try and select a 5th
  63. No can do! Now unselect a selected and select another
  64. Notice the Select All is no longer a valid option
  65. Uncheck the Limit of 4
  66. Test again, notice the limitations were removed
  67. So what happens if this was a list vs a Tile List?
  68. Stop your application
  69. In the screen designer, change the control type to List
  70. Run your app, test the functionality
  71. As you see, same code, different control type, same results!
  72. Now you ask… table too?
  73. Yep! Go ahead and change it to a table control
  74. Run and test the app
  75. Same code, works as expected on all 3 controls!

So there you go… an easy, reproduceable method of enabling multi-select on your LightSwitch list controls. You can even have multiple lists on the same screen, each will behave independently. We'll leave that up to you to go play around and test. Our sample project already has a multi-list screen if you want to go check it out.

We’ve added functionality to persist selections for a session. Its also a key part for a table control if you are going to allow your clients to change the sort order by clicking on the columns. You’ll set the control to persistSelections and it won’t be a problem. Check out the sample project for the code, its quite simple. Also check out the live preview on how it works.

Obviously if you are using an ItemTap to get to an edit/view screen, you would not implement this, but you could, since we no longer take that over and we do allow for persistent selections. But for most, selection and batch processing, this is the ticket.

One final note regarding the Select All functionality. We are selecting and working with rendered items. So with virtual scrolling, not all items from a query have been returned and rendered. Which means if you do a Select All, scroll and more data comes down, the new data is not selected. Of course one could go and press the Select All button again, or you could do a dataBind and fire off another Select All. But I don't see many instances of where that is appropriate. But you could.

Enjoy! More to come…

36 thoughts on “LightSwitch 2013 HTML Client – Easily add Multi Item Selection to your Lists and Tables!

  1. Ramin says:

    Hi Dale, Great Job! and it works fantastic but I have a situation, when I use post render on List Items to mark them disabled if they already added enabling Multi Select still allows selecting disabled items. Any idea how I can make it to not to select if List items are marked contentItem.isEnabled = false

  2. Juan Montoya says:

    I am using a table grid. When I add a button in each row to call a dialog window: The multi-select is blocking the button click event. If I comment out the multi-select line “lsWire.list.enableMultiSelect(contentItem);” the event of the button works well. Any ideas on how to solve tis problem. Thanks in advance.

  3. Hi Dale, awesome as usual!

    I’m one of those people that wants it all :-)

    I’m trying to incorporate some of the stuff mentioned in the post above into a screen designed with your also excellent ‘Enhanced Grid’ template; for example, enabling multiselect, which appears not to be incorporated in that project.

    Picking up your list/table etc post-render code (for the enhanced grid/table):

    contentItem.enhancedTable = new itgLs.EnhancedTable({
    element: element,
    contentItem: contentItem
    });

    I’ve tried various combinations/positions of this line of code as in the post above within this stub:

    lsWire.list.enableMultiSelect(contentItem);

    or even:

    lsWire.list.enableMultiSelect(contentItem.enhancedTable)

    To no avail! Code breaks in lswire.js line 415:

    contentItem.screen[contentItem.name].selectedItem = itemData

    with a null reference.

    Any ideas please?

    Is it even possible to ‘mix-up’ the two projects’ features?

    • I had the same issue. I tracked it down to the fact that I had more than one screen instance of a collection (e.g. my collection is “Options” and my screen controls were “Options” and “Options1″)(by default, LS adds a “1” to the next instance of the control. I determined that the screen control “Name” must match the collection and it works. It would not work on the second “Options1″ control at all. I always got the same error. The error “sort of” gives an indication like that since it’s looking for “contentItem.name”.

      Hope this helps!
      Scott

  4. DKSim says:

    hi
    There are questions
    Unzip the file, run the example, the error is emanating
    What is the problem?

    And you can not, depending on the starting 29
    Are not multiple-choice.

    A warning that the package is useless out
    Do you know why?

  5. Sudheer says:

    Awsome post, Is it possible to put the select All button on command bar ???

  6. alex says:

    I have used your grid control but in couple of projects. I am trying to figure out how to add paging using WCF RIA. Any ideas

  7. Isaac says:

    awesome demo…i would love to know how to implement the functionality for the tilting help menu… :)

    thanks!

    • dwm9100b says:

      Thanks Isaac… Took a while to get that tilting working with LightSwitch, but the possibilities are cool when it comes to help or menus. I’ll try to put up a post on how to accomplish this if there is interest.

  8. harroot says:

    Great article, thank you for sharing this with us,
    But there is one issue I’m stuck with maybe some of you have seen it before.
    in the lswires.js file like 444
    $.each(selected, function (item) {

    // Get our data out of the jQuery cache
    var entity = $.cache[item[$.expando]].data.__entity;
    if (entity !== undefined)
    data.push(entity);

    });

    $.cache[item[$.expando]] – element is always undefined !!!

    but the “selected” variable contains the list of td elements that I have selected on the table.
    Can you please advice, what I’m doing wrong.

  9. […] LightSwitch 2013 HTML Client – Easily add Multi Item Selection to your Lists and Tables! […]

  10. Sulaiman.tanveer says:

    i really liked your post but have some awkward kind of issue at my end, when i publish the light switch application in release mode the alert scripts and script below it seems to not work.
    Any suggestion on what am i doing wrong.

    thanks

  11. Sven says:

    Hi,
    I get an error when trying to select:

    contentItem.screen[contentItem.name].selectedItem = itemData;

    The reference is null or undefined.

    Followed your instructions.

    By the way, I cannot find lo-dasg.js, only lodash.js. The same?

    Regards
    Sven

    • dwm9100b says:

      Hmmm… I don’t see in the posting lo-dasg.js… I’m checking again the instructions. Did you download the sample project and get that to run successfully?

      • Sven says:

        Hi
        I meant lo-dash.js
        Sven

      • Sven says:

        Yes. Your project works great, nut not mine :(

      • Sven says:

        Hi,
        The selectAll works though, but not when I click on one line.
        Sven

      • Sven says:

        Hi again,
        This is strange. I removed all: contentItem.screen[contentItem.name].selectedItem = xxx. in your .Js

        Now it all works. Know why?

        I forgot. Great work with this one, It’s super nice.
        Sven

      • Sven says:

        Hi,
        the render worked but obviously it did not trigger “selectedItem”
        It was fun for a while :)

        Sven

    • dwm9100b says:

      Re the error… are you able to zip up your project and send it over? I’m not able to repro…

      • Sven says:

        Hi,
        The project is so big and have multiply connections
        I will have to leave this for now.
        Maby the complexity of my project messes things up.
        Sven

    • dwm9100b says:

      One thing I left out… which I’ll add into the instructions is this… LightSwitch adds a default ItemTap for the list, but we never added the screen. So delete the ItemTap in properties.

  12. Miles James says:

    in the “Browse Employees and Products” view on the live test drive site, the Product list view works fine. But, if you change the sort by selecting a column header, the multi-select no longer works.

  13. ORIC.CA says:

    Article very didactic, easy to implement and very powerful!

  14. Very creative Dale. Thanks a lot.

  15. Great work but FYI, using your ‘MultiSelect Preview’, there appears to be a bug. Using Desktop IE11, First entry ‘Select All’ doesn’t select the last customer but if you ‘Unselect All’ then ‘Select All’ it works OK. Worse on Android (Nexus 7) because as you scroll down the bottom block of customers do not show as selected i.e. are not pale Blue. Unselecting all then selecting all again does not seem to fix the problem.

    I haven’t had time to read the details of your blog yet so if there’s some reason you don’t select all when the button is pressed then it’s not a bug but a feature (as we say). Anyway, as a users, it wasn’t what I expected. BTW My quick test showed that ‘Limit’ code seemed to work well.

    • dwm9100b says:

      Hey thanks for the comments. LightSwitch works based on virtual scrolling. The selectAll will only select what has been loaded into the DOM at the time selectAll is pressed. LightSwitch by default loads 45 at a time. Once you start scrolling down it keeps loading more. Which means you will see unselected items if its a large list. Which in reality you probably wouldnt be selectingAll. I talk about this at the bottom of the Blog post. Perhaps I’ll force the loading of all the items in the preview.

      • Yeah I thought you might have a reason and I could see that it was not selecting beyond the data refresh and that’s kind of random maybe based on whether the customer tiles display 1-up, 2-up, 2-up etc. i.e. the form- factor or the browser and the amount of scrolling involved. Because it was inconsistent depending on the two browser / form-factors I chose I would prefer that it actually did select ALL customers. I might want to assume that, without scrolling, that everything had been chosen regardless of the technical vagaries of the development tools defaults. i.e. ‘Dumb User’ POV.

        So to that extent I would support a full load as the default in this case or a more complicated page by page selection option i.e. only what I can see is selected when I say ‘Select All’ IOW ‘Select All Visible Customers’.

        Not sure to what extent loading all customers would slow down the load though. You certainly wouldn’t try that with a million customers in the DB.

        I can see a use for this in user config e.g. which States are you following, the users selects them and you save the data to a config to default for next time. Plenty of other uses too. I very much appreciate you work.

      • Cheers. Working as I would expect now. Consistent on Droid, IE11 DT & iOS. Impressively instant selection on my iPhone4 BTW. I look forward to getting the time to dive into your blog and figure out what you’ve done to achieve this result.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 160 other followers

%d bloggers like this: