locked
How set the value of a details picker using JavaScript in response to a user selecting a value for a different details picker RRS feed

  • Question

  • When the user selects a value in the details picker for one field, I would like to programmatically set the value for another field that also uses a details picker.  I've tried the following:

    myapp.AddEditTheEntity.Field1_postRender = function (element, contentItem) {
        contentItem.dataBind("value", function (value) {
            value.TheEntity_Field2 = myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(123);
        });
    };

    But I'm getting "Cannot read property 'entityState of undefined' using this approach.  Any ideas?

    Thanks!


    Wednesday, June 4, 2014 12:16 AM

All replies

  • I would put this code in the entity, rather than the screen, using the Field1_Changed event handler.

    Check this.Details.Properties.Field1.IsChanged to make sure the user has actually changed the value because the Changed event is also called when the value is first loaded from the database.


    Simon Jones
    If you found this post helpful, please "Vote as Helpful". If it actually answered your question, please remember to "Mark as Answer". This will help other people find answers to their problems more quickly.

    Wednesday, June 4, 2014 8:22 AM
  • I would like to have this functionality at the screen because there is not a one-to-one relationship between these fields.  Depending on the value selected for Field1, Field2's value must be inspected, possibly changed, cleared, or set to a default value and the user must confirm the suggested value.  So I would like to provide immediate feedback to the user as Field1 is changed.
    Wednesday, June 4, 2014 12:45 PM
  • Hi Calvin,

    You're on the right track but a couple things:

    myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(123)

    This code points to a query object which needs to be executed like so:

    myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(123).excecute()

    The execute method returns a promise object so you must use .then() method to get the result like so:

    myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(123).excecute()

    .then(function(result){...do something with result...});

    Setting a details picker with dataBind of another picker work for me like so:

    myapp.AddEditOrderDetail.OrderHeader_postRender = function (element, contentItem) {
        // Write code here.
        contentItem.dataBind("value", function (newValue) {
            myapp.activeDataWorkspace.ApplicationData.Stocks_SingleOrDefault(4).execute()
            .then(function (result) {
                contentItem.data.Stock = result.results[0];
            });
            
        })
    };

    Note:  Because of how dataBind works, this code will set the second picker value every time the field renders - possibly overwriting a previous value.  You could add a check for no value or use addChangeListener instead which would only execute when the value of first picker changes.

    HTH,

    Josh


    • Edited by joshbooker Wednesday, June 4, 2014 1:08 PM
    Wednesday, June 4, 2014 1:07 PM
  • Thanks Josh.  Unfortunately I haven't been able to infer from your post how precisely to implement the behavior I seek.  In the following code, the joined promise's then() callback isn't getting called.  How does one instruct the promise to execute?

    myapp.AddEditSomeEntity.Field1_postRender = function (element, contentItem) {
        contentItem.dataBind("value", function (value) {
            var flag1 = !!(value && value.Option1);
            var flag2 = !!(value && value.Option2);
            var option1;
            var option2;
            var promise1 = myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(1)
                                .execute().then(function (result) { option1 = result; });
            var promise2 = myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(2)
                                .execute().then(function (result) { option2 = result; });
            WinJS.Promise.join(promise1, promise2).then(function () {
                if (flag1) {
                    contentItem.data.SomeEntity.setField2(option1);
                }
                else if (flag2) {
                    contentItem.data.SomeEntity.setField2(option2);
                } else {
                    if (contentItem.data.SomeEntity.Field2 === option1 || contentItem.data.SomeEntity.Field2 === option2) {
                        contentItem.data.SomeEntity.setField2(myapp.activeDataWorkspace.Data.Field2s_SingleOrDefault(0));
                    }
                }
            });
        });
    };


    Wednesday, June 4, 2014 3:48 PM
  • I don't know for sure since I haven't done any promise chaining.  Perhaps the .join is executing, but error prevent .then from executing.  I wonder whether it's a variable scope thing?  Try defining vars at the myapp namespace like so:

    myapp.flag1 = ...etc

    You could also add the error arg to .then and see if it's failing silently.

    Here's a similar post:

    http://social.msdn.microsoft.com/Forums/vstudio/en-US/9d30b5ef-5251-4193-88bc-df8588d5f608/how-to-run-multiple-screen-query-using-promise-in-lightswitch-html-client?forum=lightswitch

    Hopefully some more experienced WinJS folks will chime in.

    HTH,

    Josh

    Thursday, June 5, 2014 11:36 AM