Using Web History for Panel Navigation

This Q&A forum allows users to post and respond to "How Do I Do ....." questions. Please do not use to report (suspected) errors - you must use your regional help desk for this. The information contained in this forum has not been validated by LANSA and, as such, LANSA cannot guarantee the accuracy of the information.
Post Reply
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Using Web History for Panel Navigation

Post by jyoung »

Hi, I am spiking out a solution that can use web history to maintain back button support when user "transitions" between panels.

TL;DR
When adding history, the first "click" of the back button works as expected, but subsequent clicks require two clicks of the back button.

I have a web page that is composed of 4 Panels (Green, Red, Blue and Purple), an application object to manage the panel transitions and a PanelManager to deal with adding panels to a layout.

If you execute, MMSPanelPage, you can see the app in action. Clicking through the panels on the left transitions to each panel and the panel identifier is added to the URL via #SYS_WEB.History. Click through to the purple panel and then click your brower's back button. The first click works as expected, the blue panel is displayed. The second click does nothing (I would expect the red panel to be displayed), but the third click transitions to the red panel. Like wise for the previous green panel.

If you open your brower's dev tools, I have added some Console.Log statements to help track it down. I tried some crazy tricks like adding all the panel history to a collection and always getting the last one, nothing seems to work.

Attached is the export. Could use some advice or guidance on how to make this work.

Thanks,
Joe
Attachments
QuickExport20160222125540.zip
(16.45 KiB) Downloaded 1294 times
User avatar
Stewart Marshall
Posts: 417
Joined: Thu Nov 05, 2015 5:25 pm

Re: Using Web History for Panel Navigation

Post by Stewart Marshall »

Hi Joe

I found exactly the same issues when making the xDemoWebBackForward example. It's slightly simpler than yours, but the concepts are the same.

Your current processing is similar to this

Click green. Show green. Add green.
Click red. Show red. Add red.
Click blue. Show blue. Add blue.
Click back. Show red. Add red!!!!
Click back. Show red, but as it's already red, ignore.
Click back. Show green. Add green.

All processing has to go via the URLchanged event. This is a necessity for all back, forward and deep linking processing. However, not all navigations are equal. If a user clicks a button to do something, that should be added to the history, but use of Back/Forward should not. They just navigate through it.

I've made a couple of alterations to the code. The application object now has an AddToHistory method. This is called by each of the items in the list when they're used.

Regards
Attachments
QuickExport20160223112631.zip
(15.91 KiB) Downloaded 1320 times
Stewart Marshall

Independent IT Consultant
www.marshallfloyd.com.au
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: Using Web History for Panel Navigation

Post by jyoung »

Ok, I see what you did there.

I gotta remember about those demo apps, lots of good information in there if you remember to go look for it. :D

Thanks for the help.
jyoung
Posts: 694
Joined: Thu Jan 21, 2016 6:43 am
Location: Oklahoma City, OK USA

Re: Using Web History for Panel Navigation

Post by jyoung »

I realize this is an old topic, but I've encountered another issue related to the topic so I thought I would add it here.

While adding to the history works as expected regarding navigation, there seems to be an anomaly with other querystring parameters.

In essence what I am trying to do is add an entry to the history keeping the current querystring values and/or replacing certain values so that history would become
  1. ?panel=ABC&Trace=True
  2. ?panel=DEF&Trace=True
  3. ?panel=GHI&Trace=True
What I have discovered is that when I first add and entry to the history it removes all the existing querystring parameters such as debug info, trace etc. So I thought to copy the current querystring parameters and add them to the history as well and that works the first time the entry is added.

Subsequenent adds however seem to concat the values on the existing querystring whereas the initial add, replaced the entire querystring.

For example:
If the querystring is `?myvalue=123&trace=true` and I add `panel=ABC` then the querystring becomes `?panel=ABC`.

If I copy the the querystring parameters, add my panel parameter and then add all that to the history the querystring becomes `?myvalue=123&trace=true&mypanel=ABC`. If I copy the parameters, change the panel parameter add it to the history the querystring becomes `?myvalue=123&trace=true&mypanel=ABC&myvalue=123&trace=true&mypanel=DEF`.

It seems the first call to Add does a replace and subsequent calls to Add concatenate.
Has anyone else seen this behavior or know how to deal with it?

This is the code I am using, perhaps I am doing something wrong?

Code: Select all

define_com class(#PRIM_ACOL<#PRIM_WEB.URLParameter>) name(#queryStringParameters)

mthroutine name(AddToPanelHistory) access(*PRIVATE)
define_map for(*INPUT) class(#STD_STRNG) name(#panelId)
define field(#queryString) type(*STRING)

#queryStringParameters.RemoveAll

for each(#urlParameter) in(#SYS_WEB.URLParameters)
* don't add a panel, we are going to add it later
continue if(#urlParameter.Name.Uppercase = PANEL)

#SYS_APPLN.TraceMessageText( ("Adding &1:&2 to parameters").Substitute( #urlParameter.Name #urlParameter.Value ) )

if (#queryStringParameters.Contains( #urlParameter ) = False)
#queryStringParameters.Insert( #urlParameter )
endif
endfor

* build up the querystring 
for each(#queryStringParameter) in(#queryStringParameters)
if (#queryString.CurChars = 0)
#queryString += ("&1=&2").Substitute( #queryStringParameter.Name #queryStringParameter.Value )
else
#queryString += ("&1&2=&3").Substitute( '&' #queryStringParameter.Name #queryStringParameter.Value )
endif
endfor

* add the panel id and add it to the history
if (#queryString.CurChars = 0)
#queryString += ("&1=&2").Substitute( panel #panelId )
else
#queryString += ("&1&2=&3").Substitute( '&' panel #panelId )
endif

#SYS_WEB.History.Add( #queryString )

endroutine
User avatar
Stewart Marshall
Posts: 417
Joined: Thu Nov 05, 2015 5:25 pm

Re: Using Web History for Panel Navigation

Post by Stewart Marshall »

Hi Joe

Here's a simple page showing history working as it should. Run it from the IDE to get additional parameters in the QueryString.

Every time a label is clicked, its caption is added to the history. As the sequence of the parameters in the QueryString isn't important, I ignore a "Panel" item if its there and then tack it on the end.

Code: Select all

Begin_Com Role(*EXTENDS #PRIM_WEB) Height(488) Width(769) Theme(#SYS_THEME<2015Blue>)
Define_Com Class(#prim_labl) Name(#Label1) Caption('Panel1') DisplayPosition(3) Left(32) Parent(#COM_OWNER) TabPosition(3) Top(64) TabStop(False) ThemeDrawStyle('LightTitle') Height(34) Width(209) Alignment(Center) VerticalAlignment(Center)
Define_Com Class(#prim_labl) Name(#Label2) Caption('Panel2') DisplayPosition(2) Left(32) Parent(#COM_OWNER) TabPosition(2) Top(104) TabStop(False) ThemeDrawStyle('LightTitle') Height(34) Width(209) Alignment(Center) VerticalAlignment(Center)
Define_Com Class(#prim_labl) Name(#Label3) Caption('Panel3') DisplayPosition(1) Left(32) Parent(#COM_OWNER) TabPosition(1) Top(144) TabStop(False) ThemeDrawStyle('LightTitle') Height(34) Width(209) Alignment(Center) VerticalAlignment(Center)

Define_Com Class(#prim_kcol<#prim_labl #xDemoCaption>) Name(#Labels) Style(Collection)

Evtroutine Handling(#Com_owner.CreateInstance)

For Each(#Member) In(#Com_owner.ComponentMembers) Operation(*Instance_of #prim_labl)

#Labels<#Member.Caption.UpperCase> <= #Member

Endfor

Endroutine

Evtroutine Handling(#Labels<>.Click) Com_Sender(#Sender)

#Com_owner.AddHistory( #Sender.Caption )

Endroutine

Mthroutine Name(AddHistory)
Define_Map For(*Input) Class(#Prim_Alph) Name(#Panel)

Define_Com Class(#Prim_alph) Name(#QueryString)

For Each(#Parameter) In(#sys_web.URLParameters)
Continue If(#Parameter.Name.UpperCase = Panel)

If (#QueryString <> "")
#QueryString += "&"
Endif

#QueryString += #Parameter.Name + "=" + #Parameter.Value

Endfor

#QueryString += "&Panel" + "=" + #Panel

#sys_web.History.Add( #QueryString )

Endroutine

Evtroutine Handling(#sys_web.URLChanged)

#Labels<>.ThemeDrawStyle := LightTitle

If (#sys_web.URLParameters<Panel> *IsNot *null)

#Labels<#sys_web.URLParameters<Panel>.Value.UpperCase>.ThemeDrawStyle := DarkTitle

Endif

Endroutine

End_Com
Regards
Stewart Marshall

Independent IT Consultant
www.marshallfloyd.com.au
Post Reply