locked
Very Dissapointed - nested Add/Edit isn't natively handled RRS feed

  • Question

  • When creating an addedit screen, not all the expected info may be present in a dropdown (detail picker) and may have to be added. A simple add button should be available for the user to add the content.

    Trying to link a child addedit screen should be straightforward as it is highly common in forms applications. But for whatever reason, the button will open the child screen, but the entityState of the screen is read-only and replaces the save icon with a check mark.

    I have searched high & low for a work-around and the closest I found was this: 

    How to save nested add/edit screen data before coming back to first screen 

    which suggests using the following code in the afterClose event of the caller screen:

    addEditScreen.details.dataWorkspace.[DataSourceName].[Tablename to add record too].dataService.saveChanges();

    This did not work and I am 'very dissapointed' this isn't native and don't know where to go to now.

    Here is my attempt. Maybe I'm just a knucklehead, but it doesn't add the record or kick an error of any kind.

    myapp.AddEditTSA_ACCNT.ShowAddEditTSA_CLNT_Tap_execute = function (screen) {
        //Create AddNewScreen For Screen Control
    
        myapp.showScreen("AddEditTSA_CLNT", null, {
            beforeShown: function (AddEditScreen) {
                var setNewScreen = new myapp.TSA_CLNT();
                var setParam = 0;
                setNewScreen.CLNT_PK = setParam;
                AddEditScreen.TSA_CLNT = setNewScreen;
                
            },
            afterClosed: function (AddEditScreen, navigationAction) {
                if (navigationAction === msls.NavigateBackAction.commit) {
                    AddEditScreen.details.dataWorkspace.TSAWRKFLWDEVDB.TSA_CLNTS.dataService.saveChanges();
                    //screen.TSA_ACCNT.TSA_CLNT = AddEditScreen.TSA_CLNT;
                    //screen.TSA_ACCNT.details.refresh();
                }
            }
        });
    };

    It is a major client dis-satisfier to make them back out, find, and add through a browse screen when a link should be easily accessible. Let me know if anyone has found another way around or if my script is off.

    Thanks!

    Friday, April 15, 2016 7:48 PM

Answers

  • Thanks novascape, your suggestion led me down a path to the solution.

    There was a more simple solution to this and it was cancelChanges().then('do what you want'). I almost went down a crazy path, but took a step back and thought what needed to be done was to discard changes. When LS opens an addedit screen, it essentially locks changes like a locked record in a database; and prevents other changes. This needed to be released before other records can be applied.

    It's a pain to cache all values, but less painful than alternative workarounds.

    Essentially what has to happen is in the button execute method:

    1. cache current user inputs
    2. cancel changes on the current addedit screen (in my case TSA_ACCNT)
    3. wrap the myapp.showscreen in a '.then(function() {})'
    4. add another myapp.showscreen function in the afterClose option
    5. reset cached user inputs
    myapp.AddEditTSA_ACCNT.ShowAddEditTSA_CLNT_Tap_execute = function (screen) {
        var newSetupConfig = screen.TSA_ACCNT.TSA_WRKFLW;
        var newLD = screen.TSA_ACCNT.AC_TD;
        // cache additional user input values
    
        myapp.cancelChanges().then(function (changeFocus) {
            myapp.showScreen("AddEditTSA_CLNT", null, {
                beforeShown: function (AddEditScreen) {
                    var setNewScreen = new myapp.TSA_CLNT();
                    AddEditScreen.TSA_CLNT = setNewScreen;
                },
                afterClosed: function (AddEditScreen, navigationAction) {
                    if (navigationAction === msls.NavigateBackAction.commit) {
                        myapp.showScreen("AddEditTSA_ACCNT", null, {
                            beforeShown: function (addEditAccnt) {
                                var newAccnt = new myapp.TSA_ACCNT();
                                newAccnt.TSA_CLNT = AddEditScreen.TSA_CLNT;
                                newAccnt.TSA_WRKFLW = newSetupConfig;
                                newAccnt.AC_TD = newLD;
                                // set additional user input values
                                addEditAccnt.TSA_ACCNT = newAccnt;
                            },
                            afterClosed: function () {
                                myapp.showBrowsePipeline();
                            }
                        })
                    }
                }
            });
        });
    };

    • Marked as answer by FaithNoMore Monday, April 18, 2016 4:05 PM
    Monday, April 18, 2016 4:05 PM

All replies

  • Interesting question and I can see why this is an issue. I can't think of a way to save the added client independently from the underlying screen. How about setting the screen.Account.Client = AddEditScreen.Client in the afterClosed() function? That should cause the Account to be linked to the new Client and both the Account and the new Client will then be saved when you save the Account. You would however have to make sure that all validation of the Client is completed on the popup a client edit screen, otherwise the user experience when saving the Account will not be ideal if Client validation fails at that point.

    Regards, Xander. My Blog

    Saturday, April 16, 2016 8:48 PM
  • Thanks novascape, your suggestion led me down a path to the solution.

    There was a more simple solution to this and it was cancelChanges().then('do what you want'). I almost went down a crazy path, but took a step back and thought what needed to be done was to discard changes. When LS opens an addedit screen, it essentially locks changes like a locked record in a database; and prevents other changes. This needed to be released before other records can be applied.

    It's a pain to cache all values, but less painful than alternative workarounds.

    Essentially what has to happen is in the button execute method:

    1. cache current user inputs
    2. cancel changes on the current addedit screen (in my case TSA_ACCNT)
    3. wrap the myapp.showscreen in a '.then(function() {})'
    4. add another myapp.showscreen function in the afterClose option
    5. reset cached user inputs
    myapp.AddEditTSA_ACCNT.ShowAddEditTSA_CLNT_Tap_execute = function (screen) {
        var newSetupConfig = screen.TSA_ACCNT.TSA_WRKFLW;
        var newLD = screen.TSA_ACCNT.AC_TD;
        // cache additional user input values
    
        myapp.cancelChanges().then(function (changeFocus) {
            myapp.showScreen("AddEditTSA_CLNT", null, {
                beforeShown: function (AddEditScreen) {
                    var setNewScreen = new myapp.TSA_CLNT();
                    AddEditScreen.TSA_CLNT = setNewScreen;
                },
                afterClosed: function (AddEditScreen, navigationAction) {
                    if (navigationAction === msls.NavigateBackAction.commit) {
                        myapp.showScreen("AddEditTSA_ACCNT", null, {
                            beforeShown: function (addEditAccnt) {
                                var newAccnt = new myapp.TSA_ACCNT();
                                newAccnt.TSA_CLNT = AddEditScreen.TSA_CLNT;
                                newAccnt.TSA_WRKFLW = newSetupConfig;
                                newAccnt.AC_TD = newLD;
                                // set additional user input values
                                addEditAccnt.TSA_ACCNT = newAccnt;
                            },
                            afterClosed: function () {
                                myapp.showBrowsePipeline();
                            }
                        })
                    }
                }
            });
        });
    };

    • Marked as answer by FaithNoMore Monday, April 18, 2016 4:05 PM
    Monday, April 18, 2016 4:05 PM
  • Did you try Xander's suggestion setting the picker value in afterClosed of addNewScreen? Should work. Alternatively, if you don't mind altering msls script, then Chris Cook has a nice solution here: https://social.msdn.microsoft.com/Forums/vstudio/en-US/ded42323-a88d-41cf-9bc3-0a82d6f71b61/allowing-new-records-to-be-entered-created-in-a-details-picker-html-client HTH, Josh
    Tuesday, April 19, 2016 2:23 AM
  • I did try it, but don't think I did it right in retrospect. After re-reading his response again it makes sense. I foresee it coming up again shortly and will try it again in the future situation.
    Wednesday, April 20, 2016 4:33 AM
  • The fact that my entire response was in one long paragraph does not help when reading it, but I do a lot of replies on my iPad and for whatever reason, paragraph formatting on an iPad is not maintained and it all comes out as one long paragraph!

    I would be keen if someone knows how to overcome that, short of editing the raw HTML.


    Regards, Xander. My Blog

    Wednesday, April 20, 2016 4:46 AM
  • Another possibility is to use a popup on the original addEdit screen so you don't need to navigate away (thus avoiding unsaved changes and validation issues).  Include local properties for the fields you need to insert the entity to be added to the list, include a button to save changes, and wire up the button to post to a web api that adds the new entity using serverApplicationContext.  Make the ajax post a promise that refreshes the list when it's done.  I realize this is not ideal, just throwing it out there.  I am going to encounter this issue soon enough and will post if I discover anything new.
    Wednesday, April 20, 2016 2:40 PM
  • A popup could work, but I we would ideally want to reuse the existing AddEdit screen, otherwise you'd have to duplicate all that functionality into a popup, which will be a hassle if the AddEdit screen is slightly more complex than just a simple few fields.

    Regards, Xander. My Blog

    Wednesday, April 20, 2016 9:45 PM
  • I think it basically performs a something like a record lock on the intrinsic db in a pre-commit stage (speaking like Oracle); and with that left open could cause issue.

    Closing the uncommited record cleared the lock or whatever (and consequentially the user inputs). It is basically what I had to do and I can see the grayed tile in the background disappear. This freed up the staging record to be set to another.

    So storing the values in cache was the only way to retain settings. I thought maybe a function that parses the screen objects for types & values, stores them and could be recalled would have greatest general utility. Kinda ambitious though.

    Alternately, if this is assumed correct, could the form be opened without creating the dummy, uncommited record in the save pipeline (when the addedit screen appears)?

    I don't know LS from a framework perspective like you guys, but I'm learning quick.

    Thanks!



    • Edited by FaithNoMore Thursday, April 21, 2016 2:11 AM
    Thursday, April 21, 2016 12:54 AM
  • It would definitely not create/start a database lock during the pre-commit.

    The LS client side app is basically a stateless app, so the database locking will only occur when you call the server to do a save operation and the lock would only last for a brief millisecond while the operation completes. 


    Regards, Xander. My Blog

    Thursday, April 21, 2016 1:00 AM
  • I meant to compare the staging of a record like that in a db but within the LS framework.
    Thursday, April 21, 2016 1:59 AM