locked
Coding Custom Screen Navigation in Lightswitch HTML RRS feed

  • Question

  • I would like to have Button action event in LS HTML go slightly against the built-in navigation framework.

    Specifically, to have LS navigate from one AddEditScreen to another AddEditScreen automatically, triggered by this Button press event.

    The trick is this - I need it to navigate to the AddEditScreen of the "next item up" in the Browse Screen List, without returning to the Browse Screen.

    Example:

    Select item 'ABC01' on a Browse Screen > Navigate to the AddEditScreen for 'ABC01' > edit 'ABC01' > when finished editing, trigger an event that will enable LS to navigate directly to the AddEditScreen for 'ABC02' from the Browse Screen list.

    I have an open mind about what that event could be. A Button...anything at all.

    I have created a Button and chose 'Write my own method'.

    Does this look even close to code that will work, or will LS need to get the value of 'ABC01' from a query of some type?

    myapp.AddEditHoldingInventory.Method_execute = function (screen) {
    // Write code here.
    var navigateToNextScreen = function (Method) {
    
            return screen.getStrRqsNum().then(function (StrRqsNum) {
                if (!!StrRqsNum) {
    
                    return myapp.applyChanges().then(function () {
    
                        var paramValue = (Number(StrRqsNum) += 1).toString();
    
                                return myapp.ShowAddEditHoldingInventory(id);
                            }
                        });
                    });
                }

    The code above is modified by me, and I am not a programmer or developer. It is snippets from pieces I have gathered and am trying to make sense of.

    What the code is trying (miserably, I am sure) to achieve, is:

    get the value of StrRqsNumber > save the edits made on the screen > add +1 to the value of StrRqsNumber > navigate to the AddEditSCreen of the record with the new value.

    StrRqsNumber = a column with a value. It is unique and identifies an asset. This is most likely NOT the best way to achieve what I am trying to achieve, so I am here for advice. I don't have to use this value as the parameter, I just need to hit the 'next item up' from the list in Browse Screen, and then navigate to its AddEditScreen.

    Thank you very much for any input. I will be SO excited/relieved to get this behavior working.



    • Edited by CreedCor Friday, January 22, 2016 4:16 PM
    Friday, January 22, 2016 3:48 PM

Answers

  • What I want to achieve is this, for example:

    Browse Screen > Select item 1 of 15 in the list > scan in the information we need on the AddEditScreen for item 1 > hit the 'trigger', and have LS automatically Save that edit, then navigate to the AddEditScreen of item 2 of 15 > and so on.

    Here is a working solution for this:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute = function (screen)
    {///custom screen method to set selected item to next StrRqsNum
        //calc next num
        var nextNum = (Number(screen.HoldingInventories.selectedItem.StrRqsNum) + 1).toString();
        // iterate collection data to find the next item
        var nextItem = msls.iterate(screen.HoldingInventories.data)
                            .where(function (i)
                            {
                                return i.StrRqsNum == nextNum;
                            }).first();
        if (nextItem)
        {   //if found - select the item & return true
            screen.HoldingInventories.selectedItem = nextItem;
            return true;
        }
        else
        {   //not found - return false
            return false;
        };
    };
    
    myapp.BrowseHoldingInventories.TapMethod_execute = function (screen) {
        // tap method of list item on browse screen.
    
        //handy way to save/set scroll position
        var scrollTopPosition = $(window).scrollTop();
    
        //currently selected item
        var item = screen.HoldingInventories.selectedItem;
    
        //showAddEditScreen - pass item
               // beforeShown: setup binding on FieldB
                //afterClosed: if commit & select next then recurse
    
        myapp.showAddEditHoldingInventory(item, {
            beforeShown: function (addEditScreen)
            {//this executes before the screen is shown
                //find the trigger field
                var contentItem = addEditScreen.findContentItem("FieldB");
                if (contentItem)
                {   //databind to catch value change
                    contentItem.dataBind(contentItem.bindingPath, function(newValue){
                        if (newValue && contentItem.oldValue && newValue != contentItem.oldValue)
                        {   //if change then commit - this triggers close of addEditScreen
                            myapp.commitChanges();
                        }
                        contentItem.oldValue = newValue;
                    });
    
                }
            },
            afterClosed: function (addEditScreen, navigationAction)
            {//this executes after the screen is closed
                //scroll browse screen to where we left off
                $(window).scrollTop(scrollTopPosition);
                //if commit
                if (navigationAction == msls.NavigateBackAction.commit)
                {   //try to select next item in list
                    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
                    {   //next item selected then recurse
                        myapp.BrowseHoldingInventories.TapMethod_execute(screen);
                    }
                }
            }
        });
    };

    Steps to implement:

    1) Paste this code in your BrowseHoldingInventories screen code. 

    2) Then set the tap action of the browse screen item to 'TapMethod'. 

    3) Lastly change the value "FieldB" in the code to the name of the 'trigger' field on AddEditScreen. 

    When this field value is changed, the screen will commit & close, the next item on browse screen will be selected and a new instance of AddEdit will be shown.

    Let us know how is goes.

    Sample Project:

    https://github.com/joshbooker/HTML1501

    HTH,

    Josh


    • Edited by joshbooker Tuesday, January 26, 2016 7:08 PM sample
    • Marked as answer by CreedCor Tuesday, January 26, 2016 7:56 PM
    Tuesday, January 26, 2016 6:43 PM

All replies

  • Hi CreedCor,

    According to your description, you want to navigate a Add/Edit screen to another Add/Edit screen, is it right?

    Please try with following steps to achieve this requirement without any custom code. If misunderstanding, please feel free to let me know.

    1. Create a Browser screen for ABC table.
    2. Add a button to pop up a Add/Edit screen for ABC.
    3. Add a Add/Edit screen for another table (for example DEF).
    4. Add a button on ABC's Add/Edit screen and choose Navigate to DEF's Add/Edit screen as below image shows.

    Best Regards,
    Weiwei


    Monday, January 25, 2016 10:26 AM
    Moderator
  • Hello WeiWei Cai!!

    And thank you so much for your response!

    Yes, I think I can manage navigating to an AddEditScreen with a button on an AddEditScreen, the issue here is, I want it to happen automatically via a trigger of some sort. Here is the application...

    I am using LS to manage inventory. Inventory is scanned in using a bar-code scanner. For larger orders, it would take a lot of time to scan, then click 'Save', then select another item from the Browse Screen list, then scan again, then 'Save', then select another item from the list...etc etc.

    What I want to achieve is this, for example:

    Browse Screen > Select item 1 of 15 in the list > scan in the information we need on the AddEditScreen for item 1 > hit the 'trigger', and have LS automatically Save that edit, then navigate to the AddEditScreen of item 2 of 15 > and so on.

    Does that make more sense as to the application? It would really help save time and energy not having to do computer clicks between each item to navigate. Being able to scan in the information, and once we hit a specific field (the trigger field) then LS will change to the AddEditScreen of the next item in the list.

    The list on the Browse Screen will be dynamic and always changing, so I cannot just link to a static AddEditScreen with buttons.

    Thank you so much! It will be AMAZING to get this behavior going!!




    • Edited by CreedCor Monday, January 25, 2016 6:18 PM
    Monday, January 25, 2016 2:15 PM
  • Hi CreedCor,

    Please try above steps in your project and then tell me the test result. If it helpful, please mark the helpful reply as answer, which is benefit to other communities who has the same problem. If has any questions, please feel free to let me know.

    Best Regards,
    Weiwei

    Tuesday, January 26, 2016 2:35 AM
    Moderator
  • Weiwei,

    Thank you for your assistance, but I can tell by looking at your solution that it will not work.

    You have asked me to create a button that will navigate to a static AddEditScreen called DEF.

    The problem I am trying to solve is navigating to an AddEditScreen from a dynamic list. It will not always be DEF. I hope that makes sense.

    It needs to be a query and then calling that query, somehow, in LS.

    The query needs to be something like:

    Apply all changes on the AddEditScreen > LS need to hit the SQL database to SELECT the property Str123 > WHERE OrderID matches > return the value of Str123 > add +1 to Str123 > Navigate to AddEditScreen WHERE StrNumber = current value +1.


    Thank you again!


    • Edited by CreedCor Tuesday, January 26, 2016 3:26 PM
    Tuesday, January 26, 2016 2:54 PM
  • What I want to achieve is this, for example:

    Browse Screen > Select item 1 of 15 in the list > scan in the information we need on the AddEditScreen for item 1 > hit the 'trigger', and have LS automatically Save that edit, then navigate to the AddEditScreen of item 2 of 15 > and so on.

    Here is a working solution for this:

    /// <reference path="~/GeneratedArtifacts/viewModel.js" />
    
    myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute = function (screen)
    {///custom screen method to set selected item to next StrRqsNum
        //calc next num
        var nextNum = (Number(screen.HoldingInventories.selectedItem.StrRqsNum) + 1).toString();
        // iterate collection data to find the next item
        var nextItem = msls.iterate(screen.HoldingInventories.data)
                            .where(function (i)
                            {
                                return i.StrRqsNum == nextNum;
                            }).first();
        if (nextItem)
        {   //if found - select the item & return true
            screen.HoldingInventories.selectedItem = nextItem;
            return true;
        }
        else
        {   //not found - return false
            return false;
        };
    };
    
    myapp.BrowseHoldingInventories.TapMethod_execute = function (screen) {
        // tap method of list item on browse screen.
    
        //handy way to save/set scroll position
        var scrollTopPosition = $(window).scrollTop();
    
        //currently selected item
        var item = screen.HoldingInventories.selectedItem;
    
        //showAddEditScreen - pass item
               // beforeShown: setup binding on FieldB
                //afterClosed: if commit & select next then recurse
    
        myapp.showAddEditHoldingInventory(item, {
            beforeShown: function (addEditScreen)
            {//this executes before the screen is shown
                //find the trigger field
                var contentItem = addEditScreen.findContentItem("FieldB");
                if (contentItem)
                {   //databind to catch value change
                    contentItem.dataBind(contentItem.bindingPath, function(newValue){
                        if (newValue && contentItem.oldValue && newValue != contentItem.oldValue)
                        {   //if change then commit - this triggers close of addEditScreen
                            myapp.commitChanges();
                        }
                        contentItem.oldValue = newValue;
                    });
    
                }
            },
            afterClosed: function (addEditScreen, navigationAction)
            {//this executes after the screen is closed
                //scroll browse screen to where we left off
                $(window).scrollTop(scrollTopPosition);
                //if commit
                if (navigationAction == msls.NavigateBackAction.commit)
                {   //try to select next item in list
                    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
                    {   //next item selected then recurse
                        myapp.BrowseHoldingInventories.TapMethod_execute(screen);
                    }
                }
            }
        });
    };

    Steps to implement:

    1) Paste this code in your BrowseHoldingInventories screen code. 

    2) Then set the tap action of the browse screen item to 'TapMethod'. 

    3) Lastly change the value "FieldB" in the code to the name of the 'trigger' field on AddEditScreen. 

    When this field value is changed, the screen will commit & close, the next item on browse screen will be selected and a new instance of AddEdit will be shown.

    Let us know how is goes.

    Sample Project:

    https://github.com/joshbooker/HTML1501

    HTH,

    Josh


    • Edited by joshbooker Tuesday, January 26, 2016 7:08 PM sample
    • Marked as answer by CreedCor Tuesday, January 26, 2016 7:56 PM
    Tuesday, January 26, 2016 6:43 PM
  • Hello joshbooker,

    Sitting where I am sitting, this is a very impressive piece of work. Thank you very much for your time.

    For my project, I had to change:

    myapp.BrowseHoldingInventories.TapMethod_execute = function (screen) {
        // tap method of list item on browse screen.

    To:

    myapp.BrowseHoldingInventories.HoldingInventories_ItemTap_execute = function (screen) {
        // tap method of list item on browse screen.

    ...because the tap action stopped working after pasting this code.

    Right now, the 'trigger', commit, and close functions are working.

    When the StrInventoryStatus (trigger field) value changes, the screen automatically commits, and then navigates back to the AddEditScreen.

    It then selects the same item in the list IF there is no sequential next item.

    Meaning: If I edit 01, and there is no 02, it just selects the item I edited in the list and stops there. By 'selects', I mean the item in the list is highlighted.

    If there is a direct sequence in the list, meaning 01 to 02, it does select the next item in the list, but stops there.

    As of now, going from 01 to 03 does not function, nor opening the AddEditScreen off the back of the tap action.

    I will certainly keep looking at this code, but wanted to get back to you ASAP on the code you had done! Thank you so much!

    • Edited by CreedCor Tuesday, January 26, 2016 7:35 PM
    Tuesday, January 26, 2016 7:25 PM
  • It tries to select the next item by adding 1 to StrRqsNum. 

    Do you have a property 'StrRqsNum'?

    If not change all references to that in myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute

    HTH,

    Josh

    Tuesday, January 26, 2016 7:31 PM
  • Also, since you changed the method signature you need to make one more change.

    change this line:

                    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
                    {   //next item selected then recurse
                        myapp.BrowseHoldingInventories.TapMethod_execute(screen);
                    }

    to this:

                    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
                    {   //next item selected then recurse
                        myapp.BrowseHoldingInventories.HoldingInventories_ItemTap_execute(screen);
                    }

    HTH,

    Josh

    Tuesday, January 26, 2016 7:36 PM
  • I do have StrRQSNum, and it is working. It will +1 to the StrRqsNum.

    This will work in any case where I do have an unbroken sequence of RQS Numbers. This is what I asked for, so thank you very much.

    All I would need to work on now is getting the AddEditScreen to open once the next StrRqsNum is selected.

    Tuesday, January 26, 2016 7:39 PM
  • Also, since you changed the method signature you need to make one more change.

    change this line:

                    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
                    {   //next item selected then recurse
                        myapp.BrowseHoldingInventories.TapMethod_execute(screen);
                    }

    to this:

                    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
                    {   //next item selected then recurse
                        myapp.BrowseHoldingInventories.HoldingInventories_ItemTap_execute(screen);
                    }

    HTH,

    Josh

    That did it. Thank you!

    I did change this initially, as when reviewing the code I thought I would need to. It broke on that line when I started debugging. I must have done something wrong, as this time it works.

    Not sure that I can thank you enough. I am scheduled 3 of the next 5 weeks for 'Introduction to programming', HTML, CSS and Javascript classes. I am hoping this will help in all my future LS endeavors, and beyond.

    If there is a solid way to honor your time, let me know. I will definitely pay it forward in every opportunity.

    Thanks again!


    • Edited by CreedCor Tuesday, January 26, 2016 8:34 PM
    Tuesday, January 26, 2016 7:46 PM
  • So, one more thing. Selfishly, so it works for me ;). But also, so you know how your code behaves.

    I have noticed that even if the 'trigger' field value isn't changed, using the 'Save' icon on the AddEditScreen will cause the same navigation behavior. 

    I do not have to change the trigger field for all of this to happen - it will choose the next StrRqsNum value and navigate to its AddEditScreen simply by saving the edits, not only by changing the trigger field.

    Just a heads up!

    Thank you!!

    Tuesday, January 26, 2016 7:56 PM
  • You're welcome.  Glad it works. 

    To select the next item regardless of numbering you could include this code on your browse screen:

    myapp.BrowseHoldingInventories.selectNextListItem_execute = function (screen)
    {///custom screen method to set selected item to next StrRqsNum
    
        var index = $.inArray(screen.HoldingInventories.selectedItem, screen.HoldingInventories.data)
    
        if (index >= 0)
        {
            var nextItem = screen.HoldingInventories.data[index + 1];
        }
    
        if (nextItem)
        {   //if found - select the next item & return true
            screen.HoldingInventories.selectedItem = nextItem;
            return true;
        }
        else
        {   //not found - return false
            return false;
        };
    };


    Then call it inside afterClosed instead of

    if (myapp.BrowseHoldingInventories.selectNextStrRqsNum_execute(screen) == true)
    

    HTH,

    Josh


     PS Pluralsite has a recent course on LS HTML Client, and there is a free Syncfusion book Lightswitch Succinctly and of course Michael Washingtons books and site.
    • Edited by joshbooker Tuesday, January 26, 2016 8:37 PM
    Tuesday, January 26, 2016 8:35 PM
  • I will certainly check out the Pluralsite course.

    I signed up and downloaded the Syncfusion book. May be some nuggets in there - but I am pretty familiar with the LS designers - and even though reading your provided code *makes sense* to look at - I would have no idea how to begin writing it.

    I think these classes I am about to take, followed with staying immersed and helping out anywhere I can, will give me the foundation to understand more of what is going on in the Javascript and hopefully how to write the code to do these projects on my own. Or in the immediate, at the very least, contribute more to the code.




    • Edited by CreedCor Tuesday, January 26, 2016 9:20 PM
    Tuesday, January 26, 2016 9:19 PM