You are here:   Blog
Register   |  Login

May 27

Written by: Michael Washington
5/27/2013 11:12 AM  RssIcon

Visual Studio LightSwitch team member Huy Nguyen is a good person to follow on the Visual Studio LightSwitch forums. He typically provides well explained answers to difficult questions and usually provides code samples, and in some cases downloadable projects.

Previously, I created examples using techniques I learned from some of my favorite posts that he made. That article is called: Visual Studio LightSwitch Screen Navigation and Advanced JavaScript Examples.

In this article, I have created more examples from his latest articles.

Prevent JQuery Mobile From Overriding Custom Controls

In this post, Huy demonstrates how to use the data-role="none" attribute to prevent the underlying JQuery Mobile framework from automatically augmenting and styling certain controls. This can be useful when the JQuery Mobile augmentation causes problems. You can read more about it at this link.

image

For this example, we create a page called JQueryAndNonJQuery.

We place two Custom Controls on the page, one for Text Boxes and one for Buttons.

image

In the Properties for each control, we click the Edit Render Code link.

We use the following code for each control:

 

myapp.JQueryAndNonJQuery.TextBoxes_render = function (element, contentItem) {
    var $element = $(element);
    var $textbox1 = $('<input type="text" value="Normal Text Box" data-role="none"/>');
    var $textbox2 = $('<input type="text" value="JQuery Text Box"/>');
    $element.append($textbox1);
    $element.append($textbox2);
};
myapp.JQueryAndNonJQuery.Buttons_render = function (element, contentItem) {
    var $element = $(element);
    var $button1 = $('<input type="button" value="Normal Button" data-role="none"/>');
    var $button2 = $('<input type="button" value="JQuery Button" />');
    $element.append($button1);
    $element.append($button2);
};

 

When we run the project, we get the following output:

 

image

 

After Editing -- Return Focus and Browser Position to the Item

In this post, Huy shows how we can easily return a user to the last position in a list after navigating away to edit an item in that list.

To implement this, we must create a custom method to open the edit screen (rather than using the normal built-in method when we use the LightSwitch navigation wizard).

image

We click on the List and select the Item Tap in the Properties for the List.

image

We select Write my own method, and enter EditPatient for the method name.

image

The method will show in the View Model on the screen designer.

We right-click on it and select Edit Execute Code.

We use the following code for the method:

 

myapp.BrowsePatients.EditPatient_execute = function (screen) {
    // Set the scrollTopPosition
    var scrollTopPosition = $(window).scrollTop();
    // Open the Edit Screen
    myapp.showAddEditPatient(screen.Patients.selectedItem, {
        afterClosed: function () {
            // After the Edit screen is closed 
            // scroll to the saved scrollTopPosition
            $(window).scrollTop(scrollTopPosition);
        }
    });
};

 

image

When we run the application, we can scroll to a position in the list and click on an item to edit it.

image

The edit screen will display.

We can edit the item and save or close the edit screen.

 

image

When we return to the list, the list will scroll to the last position (rather than the default behavior of scrolling to the top of the list).

 

LightSwitch Client Side JavaScript Queries

This post by Huy is about creating Visual Studio LightSwitch client-side JavaScript queries. However, in it, he recommends that the poster use a wizard-like approach to resolve the issue being discussed. In this example, we will implement the solution that Huy suggests (Note: he has a link to his own sample at this link but it does not use a client-side JavaScript query).

 

image

When we run the application, we can click the Add New Patient button to add a new record.

image

We will be able to enter a Name and an Age and click the Validate button.

image

If a duplicate Name and Age are found, a validation message appears. We will have the option to navigate back.

The key thing to note in this example, is that the values are validated against the entire database using a client-side query that runs server-side. If we had a large amount of records in the database, the query would still run fast because it does not require the records to be transferred client-side to be searched.

image

We can change the information and click the Validate button again.

image

When the values pass validation, the Save button appears.

We can click the Save button to save the record.

image

The record will be saved, and it will display in the list.

Creating The Example

image

The first step is to create a AddNewPatient screen.

image

We create two Tabs and hide the second Tab.

We set the screen to hide the Tab Titles, and set the screen type to Browse (so the default Save button will not show).

image

We use the Add Data Item button to add a Patient entity.

This entity will be used to hold the final record we are constructing with the wizard.

image

We also create two string properties, PatientName and PatientAge.

We drag and drop the PatientName and PatientAge to the first Tab.

image

We also create a Validate button for the first Tab and use the following code for the method:

 

myapp.AddNewPatient.Validate_execute = function (screen) {
    // get the values entered
    var PatientName = screen.PatientName;
    var PatientAge = screen.PatientAge;
    // Always show step 2 at this point
    screen.showTab("Step2");
    screen.details.displayName = "Step 2";
    // Clear ValidationMessage
    screen.ValidationMessage = "";
    if (PatientName == null || PatientAge == null) {
        screen.ValidationMessage = "Both values are required -- Click Back and try again";
        // Hide the Save button
        var SaveButton = screen.findContentItem("Save");
        SaveButton.isVisible = false;
        // Stop processing
        return;
    }
    // Check to see if this is a duplicate -- construct a query
    var filter = "(PatientName eq " + msls._toODataString(PatientName, ":String") +
        ") and (PatientAge eq " + msls._toODataString(PatientAge, ":Int32") + ")";
    // Query the database
    myapp.activeDataWorkspace.ApplicationData
        .Patients
        .filter(filter)
        .execute()
        .then(function (result) {
            // Get the results of the query
            var currentPatient = result.results[0];
            // If there are any results show duplicate record error
            if (currentPatient != null && currentPatient != 'undefined') {
                screen.ValidationMessage = "Duplicate Found -- Click Back and try again";
                // Hide the Save button
                var SaveButton = screen.findContentItem("Save");
                SaveButton.isVisible = false;
            } else {
                // There is no duplication
                screen.ValidationMessage = "Validation passed -- Save to continue";
                // Show the Save button
                var SaveButton = screen.findContentItem("Save");
                SaveButton.isVisible = true;
            }
        }, function (error) {
            alert(error);
        });
};

 

image

The Save button is on the second Tab.

We use the following code for the method called by the button:

 

myapp.AddNewPatient.Save_execute = function (screen) {
    // Get the values entered
    var PatientName = screen.PatientName;
    var PatientAge = screen.PatientAge;
    // Set the values for the entity
    screen.Patient.PatientName = PatientName;
    screen.Patient.PatientAge = PatientAge;
    // Save and close
    myapp.commitChanges();
};

 

image

We open the BrowsePatients screen and create a button called Add New Patient.

We use the following code for the method called by the button:

 

myapp.BrowsePatients.AddNewPatient_execute = function (screen) {
    // Open the AddNewPatient Screen
    myapp.showAddNewPatient({
        beforeShown: function (addEditPatientScreen) {
            // Create new Patient here so that
            // discard will work.
            var newPatient = new myapp.Patient;
            addEditPatientScreen.Patient = newPatient;
        },
        afterClosed: function (AddNewPatientScreen, navigationAction) {
            // Refresh Patients
            screen.Patients.load();
        }
    });
};

 

Client-Side JavaScript API

image

The API methods for the client-side JavaScript queries can be found in the vsdoc.js file:

Note: For more information on the OData commands to use in the “filter” expression, see: Filter System Query Option ($filter)

 

	filter: function filter(expression) {
            /// <summary>
            /// Filters results using an expression defined
            /// by the OData $filter system query option.
            /// </summary>
            /// <param name="expression" type="String">
            /// An OData filter expression.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        orderBy: function orderBy(propertyName) {
            /// <summary>
            /// Orders results by a property in ascending order.
            /// </summary>
            /// <param name="propertyName" type="String">
            /// A property name.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        orderByDescending: function orderByDescending(propertyName) {
            /// <summary>
            /// Orders results by a property in descending order.
            /// </summary>
            /// <param name="propertyName" type="String">
            /// A property name.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        thenBy: function thenBy(propertyName) {
            /// <summary>
            /// Further orders results by a property in ascending order.
            /// </summary>
            /// <param name="propertyName" type="String">
            /// A property name.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        thenByDescending: function thenByDescending(propertyName) {
            /// <summary>
            /// Further orders results by a property in descending order.
            /// </summary>
            /// <param name="propertyName" type="String">
            /// A property name.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
            var q = new _DataServiceQuery(this);
        },
        expand: function expand(expression) {
            /// <summary>
            /// Expands results by including additional navigation properties using
            /// an expression defined by the OData $expand system query option.
            /// </summary>
            /// <param name="expression" type="String">
            /// An OData expand expression (a comma-separated
            /// list of names of navigation properties).
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        skip: function skip(count) {
            /// <summary>
            /// Bypasses a specified number of results.
            /// </summary>
            /// <param name="count" type="Number">
            /// The number of results to skip.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        top: function top(count) {
            /// <summary>
            /// Restricts results by a specified number.
            /// </summary>
            /// <param name="count" type="Number">
            /// The number of results to return.
            /// </param>
            /// <returns type="msls.DataServiceQuery" />
        },
        includeTotalCount: function includeTotalCount() {
            /// <summary>
            /// Requests that the total result count as if the skip and top
            /// operators were not applied is returned in addition to the results.
            /// </summary>
            /// <returns type="msls.DataServiceQuery" />
        }

 

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)


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