Share via


Adding a Signature Control to the LightSwitch HTML Client

LightSwitch is all about building business solutions quickly -- defining your data models & business rules and visually creating screens with a set of built-in controls. It does all the boring plumbing so you can concentrate on the real value of your applications. But LightSwitch also allows for all sorts of customizations so you don’t hit that infamous “glass ceiling”. When the team set out to build the LightSwitch HTML client, they wanted to make sure that the extensibility model was super simple and in line with the way web developers build solutions today.

With the Silverlight client, extension authors have to know about the guts of the LightSwitch extensibility model in order to provide easy-to-use extensions consumable by LightSwitch developers. There are over 100 (and growing) LightSwitch extensions on the Visual Studio Gallery (even a signature control). But with the HTML client we wanted to take advantage of the huge web ecosystem already out there, so adding customizations can be as easy as finding the JavaScript library you want and wiring it up to your app. 

The team has written a variety of articles on incorporating custom controls and data binding in LightSwitch. Here are a few:

In particular, the last one from Joe helped me immensely. Among other things, it describes the two hooks you get for UI customization in the HTML client -- the render and postRender events. If you need to modify DOM elements (i.e. controls) created by LightSwitch, use the postRender event. This allows you to augment the element like adding a CSS class or other DOM attributes. However, if you need to completely take over the rendering yourself then you do this in the render event of a LightSwitch custom control element.

LightSwitch produces single-page applications (SPAs) based on jQuery and jQueryMobile so there are a plethora of plugins available for you to use in LightSwitch. Which ones you use totally depends on what you want to provide to your users and the devices that you need to support. In this post I want to show you a quick way of incorporating a signature control based on the jSignature plugin.

You can download the full source code for my example here.

Add the Library to your LightSwitch Project

The first step is to grab the control you want. Search the web, look in a catalog, ask a friend, browse NuGet right from within Visual Studio, or (heaven forbid) write one yourself! With any custom code you bring into your application you’ll want to make sure it works for you. jSignature has a live demo, so you can test that it works on the devices you want to support before doing anything. This particular library says it works well on many devices, has a nice import/export feature, and good documentation, so that’s why I picked this one for this example.

Once you download jSignature, extract the ZIP. With your LightSwitch project open, flip to File View in Solution Explorer and drag the jSignature.min.js library into your Scripts folder under your HTML client project.

image

Next open the default.htm and add the script reference:

image

Now you’re ready to use the signature control in your LightSwitch app.

Add the Custom Control

For this example I’ve created a simple data model for tracking work orders. Once an employee completes a work order, they need to sign it. There are many ways to store the jSignature data in LightSwitch. jSignature has a variety of formats it supports so have a look at the documentation. For this example I’ll show how to store it as an Image using the Image Business Type as well as storing it in a much more compressed base30 string that can be reloaded back into the jSignature control.

So our data model looks like this. Note the two fields we’ll be using for our custom signature controls, SignatureImage and SignatureVector. I made SignatureVector of length 2000 to be on the safe side, but I’d imagine most signatures wouldn’t need that much space.

image

Next we’ll add a couple Add/Edit Details screens that work with these fields. Add a new screen and select Add/Edit Details and for the Screen Data select the WorkOrder. First one name “SignWorkOrderImage” and then add another one called “SignWorkOrderVector”

image

Now in the Screen Designer make the content tree how you like. For the SignWorkOrderImage screen I am going to place the SignatureImage on the screen twice, but one of them will be our custom control. There’s a few ways you can add custom controls to screens. If your control isn’t specific to a particular field, at the top of the Screen Designer click “Add Layout Item”, select “Custom Control”, and then you can specify the “screen” as the binding path.

However, since our binding path will be the SignatureImage field, just select the content item in the tree and change it to a “Custom Control”.

image

Next set the height and width of both the Signature controls to “Fit to Content”.

image

I’ll also set the display name of the custom control to something a little more prominent “SIGN HERE:”. So for the SignWorkOrderImage screen the content tree looks like this.

image

Similarly, for the SignWorkOrderVector screen, we’ll be working with the SignatureVector field. For testing, I’d like to actually see what the vector data is so I’ll also add a textbox to display that under the custom control. So the content tree for this screen looks like this.

image

Next we need to write some code in the custom control’s render events.

Working with Signatures as Images

Every control library will be different so you’ll need to learn the capabilities of the control itself before you can write code to render it. But once you’ve worked through the demo it’s pretty easy to figure out this particular control.

The only thing that you need to keep in mind regards to LightSwitch is that the DOM we see inside our _render method is not the “live” DOM—it’s the DOM that exists before jQueryMobile expands it. Because of this, we need to wait until the DOM is fully rendered so that we can initialize the control and hook up the change notifications. Joe taught us how to do this using the setTimeout() function.

What gets passed to us is the DOM element (element) and the data item we’re working with (contentItem). First create the control by specifying a <DIV> with an ID of “signature” and add that to the DOM. Then inside the setTimeout function we can initialize the control and then hook up the change listener. In order to get the data as an image from the jSignature control, we call getData and pass in the type we want back. The method returns an array with the type and the actual image data (ex. img[1] ).

 myapp.SignWorkOrderImage.Signature_render = function (element, contentItem) {

    //Create the control & attach to the DOM
    var sig = $("<div id='signature'></div>");
    sig.appendTo($(element));

    setTimeout(function () {
        //Initialize and start capturing
        sig.jSignature();

        // Listen for changes made via the custom control and update the 
        // content item whenever it changes.  
        sig.bind("change", function (e) {
            var img = sig.jSignature("getData", "image");
            if (img != null) {
                if (contentItem.value != img[1]) {
                    contentItem.value = img[1];
                }
            }
        });
    }, 0);    
};

We can also add a button to the screen to clear the signature – just specify this code in the button’s execute method.

 myapp.SignWorkOrderImage.ClearSignature_execute = function (screen) {
    // Write code here.
    $("#signature").jSignature("reset");
};

So when we run this screen we will see the signature control and as we perform each stroke, our image control is updated. If we save this, it will save as an image to the database.

image

 

Working with Signatures as Vectors

Saving the image directly to the database is quick and handy but the jSignature control documentation warns that it’s not supported on older versions of Android. Also the images won’t scale particularly well. So it’s probably better to store the data as vector data or something that can be re-rendered later. Like I mentioned before, there are a lot of formats you can choose from, even SVG and Base64 formats. Instead of storing the data as an Image business type in LightSwitch, change it to a standard Binary and you’re good to go.

But since the base30 format that jSignature provides is the most compact, we’ll use that for the next example. This format also allows us to load it into the jSignature control when we open the screen as well.

 myapp.SignWorkOrderVector.Signature_render = function (element, contentItem) {

    //Create the control & attach to the DOM
    var sig = $("<div id='signature' ></div>");
    sig.appendTo($(element));

    setTimeout(function () {
        //Initialize control and set initial data       
        sig.jSignature();
        if (contentItem.value != null) {
            sig.jSignature("setData", "data:" + contentItem.value);
        }

        // Listen for changes made via the custom control and update the  
        // content item whenever it changes.  
        sig.bind("change", function (e) {
            var data = sig.jSignature("getData", "base30");
            if (data != null) {
                data = data.join(",");
                if (contentItem.value != data) {
                    contentItem.value = data;
                }
            }
        });
    }, 0);   
};

When we run this screen you can see the much smaller payload for the signature. We also see the control loaded with data when we reopen it.

image

 

Wrap Up

That’s it! As you can see, adding UI customizations takes just a little knowledge of JavaScript and understanding of how LightSwitch renders the DOM. In fact, I’m learning JavaScript & jQuery through LightSwitch and I think I have just enough knowledge to be dangerous productive now :-)

Keep in mind that not all devices support all the controls out there so your mileage may vary. But I hope I demonstrated how you can easily customize the LightSwitch HTML client.

Enjoy!

Comments

  • Anonymous
    April 26, 2013
    Beth, You are amazing!!! I truly appreciate all your help. Thanks again.

  • Anonymous
    April 30, 2013
    The comment has been removed

  • Anonymous
    April 30, 2013
    Hi Josh -- with this particular control you can adjust the size by passing a settings object when you initialize the control. Make sure the custom control's size in the property sheet is set to "Fit to Content". Then initialize it the size you want: sig.jSignature({ 'height' : '300px', 'width' : '600px' }); HTH, -Beth

  • Anonymous
    July 12, 2013
    I love that control and use it for several months now. However, is there a way to display the signature "read-only" after it has been saved as a vector? Indeed, I have an edit and a view screen (two screens when I wish I could use only one but that's another subject). In the view screen I do not bind so no changes to the signature can be saved. Yet being able to draw on top of the existing signature is disturbing.

  • Anonymous
    July 17, 2013
    @François - You might want to go the image route I describe above to do this easily. The images can display read-only.

  • Anonymous
    August 16, 2013
    Tks Beth. It was not that disturbing so I kept vectors. But now I want to print my signed docs. I have a print.css file and everything is fine except... signatures don't get printed lol. I know I can use images and will do so but in the meantime do you know if I can convert my existing vectors into images? I cannot loose them. Tks. François

  • Anonymous
    August 16, 2013
    Actually signatures do get printed. It is just that the ink is white on dark theme. I "just" have to find a way to change the color of the ink when printing vectors :-)

  • Anonymous
    August 17, 2013
    Here is what I ended up doing for those interested (if any lol): I change the color of the text with the F12 option of IE and then print. Do the change before calling the screen with your signature otherwise the change is not taking into account.

  • Anonymous
    June 16, 2014
    Thanks for this, Stumbled acroos this post. I am trying to incorporate this into an existing Joomla site using RSFormPro - it's tough! Also, I'm a newbie to jquery!

  • Anonymous
    September 02, 2014
    Hi Beth, how to write the template for custom control in render event. when we chose some custom control and click on edit render code. i need the render function like below myapp.controlName_render = function (element, contentItem) {   // my code need to be added by default as template. }; can you please provide solution to this. Regards, Sumankumar G