locked
Lightswitch HTML - Basic Issue RRS feed

  • Question

  • Lightswitch started as tool to create business solutions with minimal code.

    This was largely true with the Silverlight Desktop client.

    With the shift to HTML Client, this is just not true any longer. Calculated fields are no longer available and lots of code needs to be written even for simple solutions. Code has to be written for Data Binding, Promises, AddChangeListeners.....

    The original goal for "Minimal Code/ Easy Solution" is almost completely lost!!

    A suggestion: All related code to show calculated fields for HTML client should be automatically generated by Lightswitch .

    Thursday, December 4, 2014 3:43 AM

Answers

  • I agree it would be nice and fairly simple for MS to add Computed Properties to HTML Client.  In fact if they would just include them in the model then we could do it ourselves. 

    Here's one way to do it rather similarly to SL client:

    1) Add optional property to your entity.  I have Customer and Added a property called 'CSZ'

    2) In the entity designer select HTML perspective and choose write code | created.  This adds the entity.js client side script. (customer.lsml.js in my case)

    3) Create a new script called OdataReadPatch.js in your scripts folder and paste in the this code. Also add a reference to this script after all other script refs in your default.htm.

    /*
    This script patches the OData read method 
    enabling us to inject operations before the results return to the LS runtime
    */
    var origJsonReadFunc = OData.jsonHandler.read;
    OData.jsonHandler.read = function (response, context) {
        var result = origJsonReadFunc.call(OData.jsonHandler, response, context);
        var data = response.data, results = data.results;
        if (results) {
            results.forEach(function (entity) {
                //do stuff to each entity here
    
                //call function to add Computed properties
                myapp.addComputedProperties.call(this, entity);
    
            });
        }
    
        return result;
    };
    
    myapp.addComputedProperties = function (entity) {
    
        //get entity name  ie: "LightSwitch.Customer" = "Customer"
        var entityType = entity.__metadata.type.split(".").pop();
    
        //get the entity class - this object contains all methods defined in Customer.lsml.js
        var entityClass = myapp[entityType]
    
        //build an array of property names from '_Compute' methods
        var properties = [];
        for (var p in entityClass) {
            if (typeof entityClass[p] === "function" && p.indexOf("_Compute") > 0) {
                prop = { name: p.split("_")[0], type: String };
                properties.push(prop);
            }
        };
        //console.log(properties);
    
        //add the computed prop to this entity by calling the _Compute method
        if (properties) {
            properties.forEach(function (entry) {
                var entryName = entry.name;
                var computeMethod = entityClass[entryName + "_Compute"];
                entity[entryName] = computeMethod.call(this, entity);
            });
        }
    };

    or download OdataReadPatch.js from here:

    https://gist.github.com/joshbooker/ddb4b07683e32a068d5d

    5)  Now write _Compute methods in your entity.js file (Customer.lsml.js for example) like so:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.Customer.created = function (entity) {
        // Write code here.
    
    };
    
    myapp.Customer.CSZ_Compute = function (entity, result) {
        // Write code here.
        var Me = entity;
        result = Me.City + ', ' + Me.State + "  " + Me.Zip;
        return result;
    };

    Notice how similar to SL compute method.

    Now just add the property to a browse screen and it works.

    After this is setup, adding new computed props is a simple as adding a _Compute method.

    The trick is the Odata patch which allows us to inject an operation to add the properties to each entity before the results are returned to LS runtime.

    More detail here:

    http://joshuabooker.com/Blog/Post/15

    HTH,

    Josh





    • Edited by joshbooker Friday, December 5, 2014 5:24 PM
    • Marked as answer by as4744 Monday, December 8, 2014 3:08 PM
    Thursday, December 4, 2014 11:41 PM
  • Thanks Jim.

    Have a look at this:

    http://joshuabooker.com/Blog/Post/15

    HTH,

    Josh

    • Marked as answer by as4744 Monday, December 8, 2014 3:08 PM
    Friday, December 5, 2014 5:23 PM

All replies

  • I agree it would be nice and fairly simple for MS to add Computed Properties to HTML Client.  In fact if they would just include them in the model then we could do it ourselves. 

    Here's one way to do it rather similarly to SL client:

    1) Add optional property to your entity.  I have Customer and Added a property called 'CSZ'

    2) In the entity designer select HTML perspective and choose write code | created.  This adds the entity.js client side script. (customer.lsml.js in my case)

    3) Create a new script called OdataReadPatch.js in your scripts folder and paste in the this code. Also add a reference to this script after all other script refs in your default.htm.

    /*
    This script patches the OData read method 
    enabling us to inject operations before the results return to the LS runtime
    */
    var origJsonReadFunc = OData.jsonHandler.read;
    OData.jsonHandler.read = function (response, context) {
        var result = origJsonReadFunc.call(OData.jsonHandler, response, context);
        var data = response.data, results = data.results;
        if (results) {
            results.forEach(function (entity) {
                //do stuff to each entity here
    
                //call function to add Computed properties
                myapp.addComputedProperties.call(this, entity);
    
            });
        }
    
        return result;
    };
    
    myapp.addComputedProperties = function (entity) {
    
        //get entity name  ie: "LightSwitch.Customer" = "Customer"
        var entityType = entity.__metadata.type.split(".").pop();
    
        //get the entity class - this object contains all methods defined in Customer.lsml.js
        var entityClass = myapp[entityType]
    
        //build an array of property names from '_Compute' methods
        var properties = [];
        for (var p in entityClass) {
            if (typeof entityClass[p] === "function" && p.indexOf("_Compute") > 0) {
                prop = { name: p.split("_")[0], type: String };
                properties.push(prop);
            }
        };
        //console.log(properties);
    
        //add the computed prop to this entity by calling the _Compute method
        if (properties) {
            properties.forEach(function (entry) {
                var entryName = entry.name;
                var computeMethod = entityClass[entryName + "_Compute"];
                entity[entryName] = computeMethod.call(this, entity);
            });
        }
    };

    or download OdataReadPatch.js from here:

    https://gist.github.com/joshbooker/ddb4b07683e32a068d5d

    5)  Now write _Compute methods in your entity.js file (Customer.lsml.js for example) like so:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.Customer.created = function (entity) {
        // Write code here.
    
    };
    
    myapp.Customer.CSZ_Compute = function (entity, result) {
        // Write code here.
        var Me = entity;
        result = Me.City + ', ' + Me.State + "  " + Me.Zip;
        return result;
    };

    Notice how similar to SL compute method.

    Now just add the property to a browse screen and it works.

    After this is setup, adding new computed props is a simple as adding a _Compute method.

    The trick is the Odata patch which allows us to inject an operation to add the properties to each entity before the results are returned to LS runtime.

    More detail here:

    http://joshuabooker.com/Blog/Post/15

    HTH,

    Josh





    • Edited by joshbooker Friday, December 5, 2014 5:24 PM
    • Marked as answer by as4744 Monday, December 8, 2014 3:08 PM
    Thursday, December 4, 2014 11:41 PM
  • Looks very interesting Josh!  Well done.  However, I think your gist link may be incorrect?  I'm getting a 'Whoops' message off github when I click there.
    Friday, December 5, 2014 5:20 PM
  • Thanks Jim.

    Have a look at this:

    http://joshuabooker.com/Blog/Post/15

    HTH,

    Josh

    • Marked as answer by as4744 Monday, December 8, 2014 3:08 PM
    Friday, December 5, 2014 5:23 PM