My first post, cheers!! :-)IMG_7979

First of all, I really want to thank many great people from the community for their endless post, books, forum posts!! This was such a great help for me to get of the ground. Thank you!!
Some months ago, I have started a journey to explore the LightSwitch HTML client for desktops apps. I must admit, that it was not very convincing in the first place (e.g. limited data grid, the UI wasted much space), but clients (and my boss) and me now love the clean UI and the endless possibilities!

One of my recent challenges: I would like to have some data loaded and UI being generated on application startup:

  1. Initializing global application settings
  2. Query and prepare user settings, roles, permissions
  3. Initialize screen independent header
  4. …?

But since the scope of development in the HTML client is the screen, there is no common entry point for application startup code.

Where to put the start-up code?

Put start-up code into a Screen_created method

Well, this is seems to be the documented way and works fine.

Bildschirmfoto 2014-08-09 um 13.56.32

But: It is possible that a user will start the application with a bookmark like ../HTMLClient/#/ViewCustomer/1 that will route him directly to the given screen. The default entry screen (and the my startup code) is not executed in this case.

I would need to put the startup code into *every* screen created method to make sure it is executed and make sure it does not get executed twice. Not very nice..

 

More universal: Run start-up code after msls._run() completed

The initialization of a LightSwitch html app is started in index.html.

When document finished loading, msls._run() gets executed. This promise operation will initialize the app and load the default screen (or a screen defined in the url).

 <script type="text/javascript">
    $(document).ready(function () {
       msls._run()
           .then(function () {
                // my application startup code
           }, function failure(error) {
                alert(error);
           });
      });
  </script>

Ok, great! We have a place where to put our code that is executed every time, our application is loaded.

And the second great thing: we can query data at this state – the msls.acticeDataWorkspace is accessible. (If you receive an error accessing the data workspace, it may help to delay the start-up code by setTimeout(function(){//start-up code},0).)

 

Any caveats? ..and where is the brain?

What if, any screen code relies on the init to be completed?

Well, we cannot expect the start-up code to be completed before my other screen code gets executed. That means, if any other code relies on e.g. user data to be loaded, we need our code to ‘wait’ until our init is completed.

I have decided, to create some kind of “mananger” for this init (and other things): “brain”.

At first, I defined a function for a custom application object: Brain(). This gets later instantiated as an object and is accessible via myapp.brain. It contains all application start-up logic and other custom screen-independent application code.

It relies on promises – because by using them, we can influence the order of the code to be executed. This is some really amazing stuff, but it took me some time to get my head around! I have found the the article by Justin Anderson a good starting point.

function Brain() {
    var initialized = false; // will be true when the init is completed
    var initialization; // will reference the promise object during execution
    function init() {
       // Returns a promise object that is completed
       // when the init is completed.
       // Case 1: Initialization completed
       if (this.initialized) {
          return new WinJS.Promise(function(){}); // returns completed promise
       // Case 2: Initialization started, but not completed
       } else if (!!this.initialization) {
          return this.initialization; // returns promise object of the already started init
       // Case 3: Initialization not started yet
       } else {
          this.initialization = new msls.promiseOperation(function () {
             // init code
             operation.complete();
          });
         return this.initialisation; // returns the newly created promise object of the init
       }
    }
  }

I have put the above code into a helper file brain.js and added it to index.htm right below GeneratedAssets.js.

 

Now, we need to add get the “brain” actually initialized on start-up:

<script type="text/javascript">
     $(document).ready(function () {
        msls._run()
            .then(function init_brain() {
                myapp.brain = new Brain(); // This must be initiated here because myapp will not be available earlier
                return myapp.brain.init(); // Executes the init and returns the promise object
               },
 function failure(error) {
 alert(error);
           });
      });
 </script>

 

Back to our ‘waiting’ screen code

All application code that requires the init to be completed should now be wrapped into a then() (or done) function of init(), like this:

function someScreenFunction() {
    myapp.brain.init().then(function () {
       // Screen code to execute after init is completed
   });
 }

Our anonymous function with the custom code will be registered with the init() promise object and executed after completing.

 

How does this finally work?

The init() function is designed to return a promise object that is completed when the initialization is completed. All before with then() and done() ‘registered’ functions will be executed after that.

In case (a) the init is already completed, an already fulfilled (empty) promise object is returned. The screen code gets executed right away.

In case (b) the init is not completed, the init function will return the promise object of the (first) running init operation.

In case (c) the init has not started yet, a new init is started and its promise object is returned.

 

Some questions are not answered yet

a) What happens when there is an error during init? I should put some error handling in there.

b) How to get the ‘waiting’ start-up animation of the HTML client to continue until the init is completed? msls.showProgress() may be a solution, but I have not tried it

 

I am sure there are many ways to have it a little easier – especially since I am no JS expert – and would love to have your comments on that.

Adding some ‘brain’ to my LightSwitch app – start-up code
Tagged on:

2 thoughts on “Adding some ‘brain’ to my LightSwitch app – start-up code

  • 11. August 2014 at 17:33
    Permalink

    Good job! Especially Since the current LightSwitch HTML Client breaks the screen.created functionality. I’d like to work with you on expanding the functionality if you’re up for it.

    Reply
    • 11. August 2014 at 21:44
      Permalink

      Thanks, Dale! ..and sure, I would love to develop it further with you. This may also solve the problem with your init() function in itgLsHelper. Will send you an email!

      In the end, I think that LightSwitch by itself should offer an entry point out of the box. It would be cool to have a way to inject a promise operation into the promise chain that is executed by msls._run, e.g. after the execution of msls.services.modelService.load() and before msls_shell.initialize(null, homeScreenId) gets executed. But, I should my put my wishlist on MS Connect.

      Reply

Leave a Reply to Dale Morrison Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>