You are here:   Blog
Register   |  Login

 

May 23

Written by: Michael Washington
5/23/2013 5:55 AM  RssIcon

image

To maximize performance, all applications must properly manage the flow of data. When dealing with an entity (one row of data), Visual Studio LightSwitch transfers the entire entity from the data layer to the client, the user interface (UI) layer. When dealing with collections (rows of data) LightSwitch uses Visual Collections, and is very deliberate as to how, and when it places entities in the Visual Collection.

image

The key thing to note is that LightSwitch will page the data. Meaning, it will not load all the data at one time. In our example, we have set the paging to 5 items at a time. However, when we run the application, it will typically display over 50 records when it starts.

image

When we do a network trace of the running application, we see that it makes multiple requests, 5 records at a time.

The Visual Collection API

image

The Visual Collection API allows the LightSwitch developer the ability to programmatically detect and manage the flow of data.

LightSwitch team member Huy Nguyen provides the following explanation of the Visual Collection API using a hypothetical Customers collection:

  • screen.getCustomers() will return a Promise object that will be fulfilled when the Customers Visual Collection is loaded. This is the one exposed under Intellisense, because most of the time it's what you want to use.
  • screen.Customers will return the Visual Collection representing the Customers on the screen. This is hidden from Intellisense because when you access it, it's not guaranteed that the Visual Collection is loaded. But it's useful to set up change listener, etc.
  • screen.Customers.data will return an array of all Customers loaded into the Visual Collection.
  • screen.Customer.selectedItem will return the current selected Customer in the Visual Collection.

 

screen.getCustomers() and screen.Customers.data

image

This first example will look at the .get method that returns a Promise object for the collection.

This example will also show how we can iterate through the entities returned by the Promise object using the .data property.

To set up the example, we add a Customer entity (a single Customer) to the View Model. We will call it LatestLoadedCustomer (right now it is just empty). We create a Popup and we drag the LatestLoadedCustomer entity to the Popup so that it will show when we open the Popup.

We create a button and use the following code:

 

myapp.BrowseCustomers.CallGetCustomers_execute = function (screen) {
    // Call getCustomers
    screen.getCustomers().then(function (result) {
        var index = result.data.length; // gets length of the full Customer array
        // The last Customer found in the 
        // collection will be 
        // set to LatestLoadedCustomer
        screen.LatestLoadedCustomer = result.data[index - 1]; // compensate for 0-based index
        // Show the Popup to display 
        // LatestLoadedCustomer
        screen.showPopup("LatestCustomer");
    });
};

 

image

When re run the application and click the button…

image

The last record retrieved by the method is displayed.

 

screen.Customers

image

While it is not guaranteed to be loaded, the Visual Collection allows us to easily attach handlers so that our code will run when the Visual Collection is loaded with data.

In this example we click on the Tile List that is bound to the Customer collection, and select Edit PostRender Code.  

We use the following code:

 

myapp.BrowseCustomers.Customer_postRender = function (element, contentItem) {
    // Set up a databind on screen.Customers.count
    contentItem.dataBind("screen.Customers.count", function (newValue) {
        // Update the total records display
        DisplayCustomerCount(contentItem.screen);
    });
};
// Utility
function DisplayCustomerCount(screen) {
    // If there is a Customer collection
    // display the current count
    if (screen.Customers != undefined && screen.Customers != null) {
        var strDisplayText = "Loaded Customers: " + screen.Customers.count;
        screen.details.displayName = strDisplayText;
    }
}

 

image

When we run the application we see that the number of loaded Customers will display.

We can also add the following code to the method:

 

    // Set up a databind on screen.Customers.selectedItem
    contentItem.dataBind("screen.Customers.selectedItem", function (newValue) {
        var SelectedItem = newValue;
        // do we have a selected Customer?
        if (SelectedItem != undefined && SelectedItem != null) {
            // Update the display to show the last selected Customer
            var strDisplayText = "SelectedItem CustomerName: " + SelectedItem.CustomerName;
            contentItem.screen.details.displayName = strDisplayText;
        }
    });

 

image

When we run the application and click on an Customer, the name of Customer will display in the title.

 

Manual Paging

In the previous examples, we loaded more records by scrolling down through the Tile List. We can also programmatically control the paging  by manually loading records into the Visual Collection.

image

We create a button…

We use the following code:

 

myapp.BrowseCustomers.GetMoreRecords_execute = function (screen) {
    if (screen.Customers.canLoadMore) {
        // We can load more records -- load them
        screen.Customers.loadMore().then(function (result) {
            var index = result.items.length; // gets length of the full Customer array
            // The last Customer found in the 
            // collection will be 
            // set to LatestLoadedCustomer
            screen.LatestLoadedCustomer = result.items[index - 1]; // compensate for 0-based index
            // Show the Popup to display 
            // LatestLoadedCustomer
            screen.showPopup("LatestCustomer");
            // Update the total records display
            DisplayCustomerCount(screen);
        });
    }
};

 

image

When we run the application and click the Get More Records button…

image

Additional records will be loaded into the Visual Collection, and the last record loaded will be displayed.

Note: For more advanced paging, see: LightSwitch HTML Client For The Desktop Web Browser.

 

Special Thanks

A very special thanks to LightSwitch Team member Huy Nguyen.

Download Code

The LightSwitch project is available at http://lightswitchhelpwebsite.com/Downloads.aspx

(you must have Visual Studio 2012 Update 2 installed to run the code)

13 comment(s) so far...


Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

Excellent article, Michael, especially about something so crucial to the HTML client. Your blog has fast become the "go-to" place for LightSwitch knowledge, much more so than the forums and MSDN!

I am going to suggest though, that using jQuery $.each() after loading more records from the VC is an unusual choice for what you're accomplishing here. I mean, if your application in fact needed to iterate through all the newly loaded entities and perform a function on each, the $.each() would be ideal, but using it to simply attach to the last item in the array seems like an afterthought. In your case, your VC objects have only 1 property and your paging size in only 5, but for more complex entities and bigger paging sizes, this would not be good use of computer resources.

So, to economize and to specifically retrieve the last item loaded, consider using JavaScript's array indexing property length, for example:

For CallGetCustomers_execute:
...then(function (result) {
var index = result.data.length; // gets length of the full Customer VC array
screen.LatestLoadedCustomer = result.data[index -1]; // compensate for 0-based index ... }

and GetMoreRecords:
screen.Customers.loadMore().then(function (result) {
var index = result.items.length; // gets length of newly loaded page of VC items
screen.LatestLoadedCustomer = result.items[index -1]; ... }

By lkbreth on   5/23/2013 12:08 PM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

@lkbreth - Thanks, I will update the article tomorrow :)

By Michael Washington on   5/23/2013 12:31 PM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

The article and code have been updated.

By Michael Washington on   5/24/2013 5:24 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

Michael, great site.

I've just started using LightSwitch. I'm working on a piece of code to automatically insert records based on records previously brought back to the HTML client (essentially a modified copy of the original records). I've tested code for inserting records. However I've been unsuccessful at retrieving the current records shown on the current screen. This article on the VisualCollection seemed promising. I gather that originally you looped through the records to obtain your final display. Could you show me the code snippet that your removed (using the $.(each)) to process the existing records or point me to an article that accesses existing rows of data data.

Thanks

By Max on   6/24/2013 12:20 PM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

@Max - See: http://lightswitchhelpwebsite.com/Blog/tabid/61/EntryId/1207/HUY-Volume-III-ndash-Popups-Dirty-Visual-Collections-and-Using-Prototypes-To-Calculate-Child-Collections.aspx

By Michael Washington on   6/24/2013 12:31 PM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

Thanks Michael. Than got me on the right path.

By Max on   6/24/2013 3:55 PM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

Michael

Can you set an odata filter on activedataworkspace.customers then call getCustomers then assign all results to the screen VC? I'm trying figure a way to do pure JavaScript query and refresh screen collection for a browse screen. I tried load() but the filter was not applied.
Thanks
Josh

By Jbooker on   10/1/2013 4:14 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

@Jbooker - None of the examples here use a filter. You may want to post to the official LightSwitch Forums to ask Huy for a good example.

By Michael Washington on   10/1/2013 4:16 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

Hi Michael, In this example when user clicks on Customer Tile list item, selected customer details appear in header. While loading screen set one default customer details in header, without selecting any Tile List item in CustomerList , it is possible in Light switch HTML Client, like while loading Browse Customers screen set screen.Customers.selecteditem = 10(customerId) . Give me some tips.

By sirancheevi on   10/8/2013 5:44 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

@sirancheevi - I am sorry but this is too much to cover in the comments of a blog post. Please make a post to the official LighSwitch forums. thank You.

By Michael Washington on   10/8/2013 5:48 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

Hi, I am trying to set a screen query (single) similar to your first example where you load LatestLoadedCustomer. I noticed your query did not have a query parameter. I haven't been able to get a single query without an Id parameter like yours. I downloaded your project and it works, but when I use your same project, add a new single customer and swap them out, I get the same error: "Bad request - error in query syntax." Any ideas?

By Borkith on   2/3/2014 9:43 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

@Borkith - I think you need to use the single or default method, however I have no examples I can find. Post a question to the official LightSwitch forums.

By Michael Washington on   2/3/2014 9:59 AM
Gravatar

Re: Understanding The LightSwitch HTML Client Visual Collection

I got your project to work with VS2013 by setting the query Id = new parameter "Id" and setting the screen.Id = the result.data[].Id!!! Now, I went to go do the same in my project, however, the entity I am trying to assign my single query to was just created and it's Id is "undefined." I am officially lost.

By Borkith on   2/3/2014 10:04 AM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 

Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation