Detect Popup Window Closing in Lightswitch

My last adventure with Lightswitch was trying to detect when a popup window inside a screen is closed.

You can close a Lightswitch popup window by clicking or tapping outside the popup. The jQuery Mobile popup widget that Lightswitch uses then closes the popup. However, I wanted to intercept that event and do some housekeeping such as discarding the changes made by the popup.

jquery mobile popup

The difficult thing was finding out where to put the event hookup code. Then, it was just a question of using jQuery Mobile Widget afterclose event that is triggered when a popup is closed.

The right event to listen for in my case was the rendering of the popup content. In the Lightswitch designer add a postRender event handler and associate the afterclose event of the parent object (the popup itself):

Lightswitch Deep Linking and Navigation in SharePoint Dialog Frame

Another one of my strange adventures with Lightswitch has made me look deep inside the navigation framework that Lightswitch uses. I will explain the strange symptoms, the cause I found out and the solution that worked for me.

SYMPTOMS

I have a Lightswitch app connected to SharePoint data. I have several screens, one for each list that is managed from Lightswitch. I want to be able to navigate straight to the screen I want from SharePoint, or to deep-link the screen.

To do so, I made a custom Promoted Links list. I added to this list my LS app deep URLs, such as https://appurl/HTMLClient/default.htm?SPHostUrlaaa&SPAppUrl=bbb&SPChromeColor=ccc#/ScreenName/[unique_number]. The ScreenName parameter is different for each screen, obviously. I also configured each link to open in a SharePoint dialog window.

Strange things happened. While I could open the desired screen by clicking on the promoted link, it would start displaying “Error Loading Page” message and keep a /spinning circle icon alive as if it were waiting for a long-running operation, after every navigation to and back from another screen or popup in the app.

image

These symptoms would disappear if the links were opened without dialogs (in the same tab or another browser tab). They would also disappear if I switched to another screen inside the app using the Lightswitch navigation menu.

CAUSE

I first suspected any custom JS files I added to the application. However, it was not until I used Fiddler tool to investigate the requests my app was doing that I found the answer.

Lightswitch app are Single-Page Applications (SPA). They leverage jQuery Mobile framework for Lightswitch navigation and maintaining app state in the browser. jQuery Mobile has a custom navigation feature that overrides standard browser navigation stack to be able to use Back button to go to the previous screen. In a SPA, there is only one “physical” page (default.htm) and all the further requests are done using AJAX calls to the LS backend services.

Fiddler showed me that the error messages were caused by a 404 HTTP not found response to a unknown page that was something like this: /ScreenName/IsDlg=1.

By opening any URL inside a SharePoint dialog, SharePoint automatically adds IsDlg=1 to the URL. It is used by SharePoint to hide any extra chrome such as navigation and toolbar from being displayed inside a dialog. So, my original URL was now changed to as https://appurl/HTMLClient/default.htm?SPHostUrlaaa&SPAppUrl=bbb&SPChromeColor=ccc#/ScreenName/[unique_number]&IsDlg=1. I could now reproduce the error even without SharePoint dialog, just by adding an extra query string parameter to the LS deep link URL and pasting it in the browser address bar.

Well, jQuery Mobile powered Lightswitch navigation seems to break when trying to parse a screen ID that follows the # sign and then finds another query string parameter such as &IsDlg=1. I tried to move the IsDlg parameter to the left of the screen ID. It worked, and I saw that I had to fix the URL in order for the navigation to work.

SOLUTION

I first thought of rewriting the LS URL by adding a custom HTTP module or a IIS rewrite rules but it sounded too cumbersome. I had to find a simpler mechanism to achieve the opening of a specific LS screen in a SharePoint dialog frame.

Thanks to my colleague Sergio Gallego, I was able to find a solution. I made a copy of the default.html page in LS and called it screen.htm. I then changed the ready() event handler inside the page to check for a query string parameter called “s” (for screen). It would then pass the parameter value as a parameter to the LS msls._run() method. This method takes an optional string parameter that is then used to start the LS app and open the screen with that same name.

I had to rewrite my URLs to the following schema: as https://appurl/HTMLClient/screen.htm?SPHostUrlaaa&SPAppUrl=bbb&SPChromeColor=ccc&s=ScreenName.

Here is the full code of the ready() method in the screen.htm file.

Lightswitch Custom Validation Refresh

I found an odd problem this week in a SharePoint-enabled Lightswitch HTML Client application. I am sharing the solution here in case there is somebody out there with a similar situation.

SYMPTOMS

You have a Lightswitch HTML application (banner definition in my case). You use custom validation function in beforeApplyChanges function.

Your validation works! However, when you try to correct the field that is being validated, the Save button doesn’t work anymore and it keeps the custom validation message on the screen (it says in Spanish that the end date has to be later than the start date).

image

Furthermore, you get an error message that says “Cannot continue. There are validation errors on the page”.

image

CAUSE

Apparently, Lightswitch code generator attaches the validation refresh on control events such as focus, blur, keyup etc, but only on default LS validations (data type, length, required fields and similar).

Custom validations on beforeApplyChanges are not refreshed on data changes in the controls and due to the page being in invalid state, the Save button doesn’t trigger the beforeApplyChanges function again. It’s a kind of a subtle bug in LS code generation that causes deadlock: we can’t save because the validation isn’t firing and it isn’t firing because we can’t save.

SOLUTION

Well, the best solution would be for Lightswitch to expose an additional hookup point for custom validation, one that should be refreshed automatically with any control change. However, it is improbable that it would ever be included in Lightswitch code.

The available solution for now is to register a change listener for those properties in our screen that trigger custom validation. Once the value is changed, we remove the validation errors for that field if there are any. This ensures that the Save button will work, triggering the custom validation logic again. We can hook up the change listener in the screen created event.

However, we have to be careful to unregister the change listener when the screen is closed. This technique is explained in this MSDN Forum post by Huy Nguyen.