I recently came across a requirement that made me aware of a new and interesting design consideration for Fluid development. When we design and develop Classic pages, we never had to worry about a 'Back' button and how it behaves in the context of user navigation.
Fluid 'Back' Button:
Let us say that we made a customization to the 'Personal Details' page so that on page load, we redirect/transfer the users to a custom component/page and then once done with custom activity we redirect/transfer them back to the 'Personal Details' page. Now if the user clicks on the 'Back' button on the 'Personal Details' page, we expect them to go back to the Fluid Home Page. But since we had an additional custom navigation, the user navigation 'History' alters the behavior of the 'Back' button. Sometimes, it may be desirable but what if it is not how we wanted the navigation to flow? How do we control the 'Back' button behavior and user navigation 'History'?
In my example, the 'Personal Details' page redirects to 'Custom Activity' page. Once we click 'Continue' (custom activity) the user gets redirected to the 'Personal Details' page.
There is a very simple solution to this problem and it involves just invoking a delivered function. But before I provide that solution, I wanted to share what I learned in the process. It is interesting to know how it works behind the scenes. This is just for informational purposes and it is not recommended unless you have a really complex requirement!
My Initial Approach:
Since, I could tell that there is some javascript that is tracking the user navigation, my first thought was to write some custom javascript to manipulate the 'History'.
Basically, I realized that we had to either prevent or clean up behind this AddToHistory function in the page javascript.
After digging into delivered javascripts, I found the clearHistory() function in the delivered PT_COMMON HTML object.
If we use the delivered clearHistory function, then it would clear the entire 'History' except the last navigation. So, I created a custom function (cskClearHistory) based on the delivered code. My custom function removes everything from the 'pt_history' object except for the first item (which should be the Home Page). I am sure there could be a better way to manipulate the 'History' and make the javascript more efficient but this seems to work for a proof of concept!
Javascript for Reference:
function cskClearHistory() //can be called by app component
{
var pt_history = getHistoryObject();
if (!pt_history || pt_history.size() <=1) return;
// Pop everything out except first item (Home Page)
while(pt_history.size() > 1) {
var lastRec = pt_history.pop();
}
pt_history.save();
}
I just invoked this javascript on my custom page activate peoplecode event as follows:
Now, when I navigate the same route (Employee Self Service (Home Page) > Personal Details --redirect--> Custom Activity --continue--> Personal Details, the 'Back' button points back to the 'Home Page' as expected/desired.
After writing this javascript and getting this to work as expected, I realized that this is still not a very efficient way of managing the user navigation 'History'. Sure, the javascript manipulation of the 'History' might be useful for some more complex scenarios (which was the purpose of my demonstration above) but definitely not a great idea for simple page transfers. Eventually, after digging into some of the existing Fluid pages, I found that there is a delivered function called SetTransferAttributes that helps us with these sort of transfers.
PeopleBooks Reference
Recommended Approach:
I got rid off all the custom javascript that I injected on page activate peoplecode. I just added this one line of code to my 'Continue' button before the transfer to set the transfer attributes appropriately.
PeopleCode: SetTransferAttributes(False, False);
Fluid 'Back' Button:
Let us say that we made a customization to the 'Personal Details' page so that on page load, we redirect/transfer the users to a custom component/page and then once done with custom activity we redirect/transfer them back to the 'Personal Details' page. Now if the user clicks on the 'Back' button on the 'Personal Details' page, we expect them to go back to the Fluid Home Page. But since we had an additional custom navigation, the user navigation 'History' alters the behavior of the 'Back' button. Sometimes, it may be desirable but what if it is not how we wanted the navigation to flow? How do we control the 'Back' button behavior and user navigation 'History'?
In my example, the 'Personal Details' page redirects to 'Custom Activity' page. Once we click 'Continue' (custom activity) the user gets redirected to the 'Personal Details' page.
There is a very simple solution to this problem and it involves just invoking a delivered function. But before I provide that solution, I wanted to share what I learned in the process. It is interesting to know how it works behind the scenes. This is just for informational purposes and it is not recommended unless you have a really complex requirement!
My Initial Approach:
Since, I could tell that there is some javascript that is tracking the user navigation, my first thought was to write some custom javascript to manipulate the 'History'.
Basically, I realized that we had to either prevent or clean up behind this AddToHistory function in the page javascript.
After digging into delivered javascripts, I found the clearHistory() function in the delivered PT_COMMON HTML object.
If we use the delivered clearHistory function, then it would clear the entire 'History' except the last navigation. So, I created a custom function (cskClearHistory) based on the delivered code. My custom function removes everything from the 'pt_history' object except for the first item (which should be the Home Page). I am sure there could be a better way to manipulate the 'History' and make the javascript more efficient but this seems to work for a proof of concept!
Javascript for Reference:
function cskClearHistory() //can be called by app component
{
var pt_history = getHistoryObject();
if (!pt_history || pt_history.size() <=1) return;
// Pop everything out except first item (Home Page)
while(pt_history.size() > 1) {
var lastRec = pt_history.pop();
}
pt_history.save();
}
I just invoked this javascript on my custom page activate peoplecode event as follows:
Now, when I navigate the same route (Employee Self Service (Home Page) > Personal Details --redirect--> Custom Activity --continue--> Personal Details, the 'Back' button points back to the 'Home Page' as expected/desired.
After writing this javascript and getting this to work as expected, I realized that this is still not a very efficient way of managing the user navigation 'History'. Sure, the javascript manipulation of the 'History' might be useful for some more complex scenarios (which was the purpose of my demonstration above) but definitely not a great idea for simple page transfers. Eventually, after digging into some of the existing Fluid pages, I found that there is a delivered function called SetTransferAttributes that helps us with these sort of transfers.
PeopleBooks Reference
Recommended Approach:
I got rid off all the custom javascript that I injected on page activate peoplecode. I just added this one line of code to my 'Continue' button before the transfer to set the transfer attributes appropriately.
PeopleCode: SetTransferAttributes(False, False);
Thanks Sasank for the explanation . This is very helpful . I tried this myself but on click of the button it wasn't taking me back to the homepage, there was no action at all. Is there any thing I may have missed apart from adding the JavaScript on page activate
ReplyDeleteThe custom JS function and the page activate peoplecode is all that is needed (if you are trying out my custom approach to manipulate the history).
DeleteYou may want to add a console.log message in the javascript to see if it is actually getting executed. Once you know the JS is executing, you can look into it further. Otherwise, this should be pretty straight forward.
Just an update - I saw this issue on PUM 18 and not in PUM 20. Looks like this has been addressed.
ReplyDeleteSasank
ReplyDeleteI noticed you had some code to automaticly open the navigation in 1 click instead of 2. But Cant find it..
p.s. I noticed it is doing that now randomly .. But cant reason out why
Hi William - The details for that topic should be here:
Deletehttps://pe0ples0ft.blogspot.com/2016/08/pt-855-flu-drop-down-menu-vs-navigator.html
You can also use this meta-blog for an index of all branding posts:
https://pe0ples0ft.blogspot.com/2014/11/peopletools-854-branding-part-1.html#index
Sasank, Great Post.
ReplyDeleteHave you worked with the Fluid Activity Guides, which automatically props up an 'Exit' button.
Similar to 'Back' button. the AG Exit also seems to remember the Nav Stack history. In situations where we move between one instance of AG to another instance (using redirection), 'Exit' button gives us an issue. Instead of going back to our dashboard, it goes to the previous instance of the AG.
Do you know of a way of controlling the history for the AG exit too?
Cheers
Manoj
Hi Manoj - I am assuming you already tried the SetTransferAttributes function and it did not work?
DeleteIs this a delivered Fluid Activity Guide which I can look at in a PUM Image?
Sorry for the late response, for some reason, I don't get notified.
DeleteIt is indeed delivered Activity guide and from our research it is using the 'AddToHistory' javascript function to build the stack as well, but SetTransferAttributes doesn't seem to work.
It can be replicatedwith the Activity Guide built for creating Activity Guide (i was the primary member of the team which enhanced the AG framework in 8.54, not selling myself, its the truth!!! XD).
But some customizations need to be done
Steps to Replicate:
1. Update the existing template to a newer Rendering type to make it easier.
UPdate PS_PTAI_LIST SET PTAI_AGRENDERTYPE = 'VNSP' where PTAI_LIST_ID LIKE 'PTAI_AGTMP%'
2. Modifiy the PTAI_CREATE_LIST.GBL SavePostChange to redirect to the Fluid AG Component instead of the Classic Component
At the end,
REPLACE
&url = GenerateComponentPortalURL(%Portal, %Node, MenuName.PTAI_MENU, %Market, Component.PTAI_AGSTARTPAGE, Page.PTAI_AGSTARTPAGE, "U") | "&CONTEXTIDPARAMS=TEMPLATE_ID:PTAI_AGTMP&CONTEXTIDPARAMS=PTAI_TEMPLATE_ID:" | ¤tList.ListId | "&CONTEXTIDPARAMS=PTAI_OPENSERVICEID:PTAI_AGPROPERTIES&replaceCurrentTopWindow=Y";
WITH
&url = GenerateComponentPortalURL(%Portal, %Node, MenuName.NUI_FRAMEWORK, %Market, Component.PT_AGSTARTPAGE_NUI, Page.PT_AGSTARTPAGE_NUI, "U") | "&CONTEXTIDPARAMS=TEMPLATE_ID:PTAI_AGTMP&CONTEXTIDPARAMS=PTAI_TEMPLATE_ID:" | ¤tList.ListId | "&CONTEXTIDPARAMS=PTAI_OPENSERVICEID:PTAI_AGPROPERTIES&replaceCurrentTopWindow=Y";
2. Create a New AG Template (Main Menu > PeopleTools > Portal > Activiy Guides > Maintain Templates)
When you create a new Activity Guide, a new instance is created for the template PTAI_AGTMP with the context parameter (PTAI_TEMPLATE_ID=PTAICREATE).
But when you save it for the first time, a new instance of the AG will be created with PTAI_TEMPLATE_ID = . When the user saves, he is directed from the 'Create' instance to the 'Named' instance, but to the user it is seemless
We can make use of this 'internal redirection' to simulate my problem.
3. Render the Activity guide in Fluid
/psp//EMPLOYEE//c/NUI_FRAMEWORK.PT_AGSTARTPAGE_NUI.GBL?Page=PT_AGSTARTPAGE_NUI&Action=U&Template=True&CONTEXTIDPARAMS=TEMPLATE_ID:PTAI_AGTMP&CONTEXTIDPARAMS=PTAI_TEMPLATE_ID:PTAICREATE&CONTEXTIDPARAMS=PTAI_OPENSERVICEID:PTAI_AGPROPERTIES
You should see the instance in Fluid Mode, with a Exit button on the LHS.
4. Now, Enter basic information about the Template Properties and Save.
You should be redirected to the new instance (from the 'Create' instance)
5. Click Exit.
User expects to go back to the 'Dashboard'' (or from where he landed)
But, it takes you back to the 'Create' instance instead, since there was an internal redirection
Hope this makes sense?
If you want to communicate better outside the forum, you can reach out to me through manojonline@gmail.com.
DeleteCheers
Manoj
I see the problem. It may be something to do with how the Activity Guide pages are rendered.
DeleteNot able to pinpoint the issue. Will Let you know if I find anything useful.
Hi Sasank,
ReplyDeleteThanks for sharing. The post has been very useful. I ended up using the custom clear history method you shared, since I needed just the Homepage link along in my scenario. It was very helpful of you in sharing your learning.
Thanks,
Joe
@Joe - Glad to hear that. Thank you! :)
DeleteHi Sasank - Thank you for this blog post. I'm currently looking into adding navigation to the delivered back button in order to give users a way to get back to our custom portal. Do you know if this is possible with your approach?
ReplyDeleteI would like to read a url from a query string parameter with "%Request.GetParameter" in the user's session and store that URL as navigation in the back button. Any advice would be greatly appreciated.
Regards,
-Adriane
Also, I'm attempting to do this using your initial approach, not with the delivered PeopleCode function.
Delete@Adriane Williams,
DeleteI am sorry for the delay in responding.
You are right, your requirement might need you to use a similar approach as option 1. I don't have a working solution for you at this point. You might have to write your own code to do this. You could start writing a similar javscript function that executing and iterates through the pt_history object. Then use console.log message to see how the code is flowing.
The you could manipulate the history array to introduce your link in the history. This is just a high level approach that I would take if I was working on this requirement.
That said, I am very interested in this requirement, as I find time I will try to work on this and might even create a separate blog post on this topic.
Thank you for the comment.
Hi Sasank,
DeleteThanks for getting back to me! I've been able to make some progress since my last comment, and I'm fairly close to a stable solution. Instead of using the AddToHistory function in my custom JS, I'm using the "UpdateHistory" and "UpdateLastHistoryItemUrl" in the delivered PT_HISTORY object. I'm currently working on forcing the back button to display and update on initial load of a PeopleSoft page (the back button only updates when I refresh a page after the initial load), as these functions only work if the pt_history object already has information stored in it. I will probably make modified versions of the two functions I found.
I'll update this thread as I come up with a more stable solution (hopefully) next week.
-Adriane
Hi Adriane
DeleteWere you able to come up with a solution to show the backbutton We are actually calling the fluid pages from the native IOS app and the back button is not showing up. We are also not going to the fluid tile page but to the worklist view page of the approvals. Any idea how you accomplished would be really helpful. Thanks
Vaij
Hi Sasank, We have recently cloned a peoplesoft environment and looks like we did a typo somewhere as the Fluid Back button is taking us to the wrong URL 'pspolab-2', instead of 'pscolab-2'. We looked in all the files on middleware and could not find the wrong entry, neither anywhere in the node definitions.
ReplyDeleteAny idea where we can see and correct the wrong entry?
Much appreciate your help.
Thanks,
Gyan
Gyan - If you already checked the node properties in the portal tab, nothing else comes to mind.
DeleteThis may be a good question for Oracle Support.
If you happen to find out what caused this issue, please do let us know. It will be useful for the community. I am very much interested in learning where this typo is persisting. Thanks!
Hi Sasank,
ReplyDeleteI need to update delivered back button to redirect to homepage rather than the last page. Any idea, how we can implement it?
Thanks,
Punam
Thank you Shashank. I resolved my problem by using viewurl function in custom fieldchange.
DeleteHi Sasank,
ReplyDeleteI am new to Fluid PS, we have a requirement to design custom self service page, when we open the page in small device it is responsive but looks same like laptop one, did you got a chance to create any custom page of ESS from scratch, if so can you let me know how to change header for that page like it shows in Personal details or Benefits summary page. Thank you for all your posts in this blog it is so helpful.
Hi shasank.
ReplyDeleteWe are not able to see the back button when navigating from find object navigation link. But the same page when viewed directly we are able to see the back button
Are there any updates to this thread? I'm trying to work around the same issue as Manoj described above. Thanks!
ReplyDeleteUnfortunately, I don't have any further updates on that thread.
DeleteHi Sasank,
ReplyDeleteWe have an issue that when we hit back button instead of going to component page with details, it takes to search page of component. Is it expected behavior or do we need to add any parameters to SetTransferAttributes function.
Not entirely sure without knowing how this component works. But you may not need to pass any additional parameters in the SetTransferAttributes. You may need to pass any necessary parameters (based on component search behavior) in the Transfer function that is subsequent to the SetTransferAttributes function.
Delete
ReplyDeleteI have a search Page N_RNAVM_MAIN
That will list entries ,
And then Based on selection it went to the Maintenance Component , Thus when they completed , Using Back Button it went Back to Search Page … Easy
But I created a notification
Initially that Notification went directly to the Maintenance Page , Worked. Problem there was no back to search page…..
SO I am trying to send the Search page … with the ID as a parameter ..
Thus if I see a parameter I go directly to Maintenance Page and Back Button SHOULD Show search Page But it does not.
I have tried a couple of things .. But it seems simple… transfer, viewurl etc… what am I missing .. or is it the placement I tred pre and post display
ReplyDeleteI have a search Page N_RNAVM_MAIN
That will list entries ,
And then Based on selection it went to the Maintenance Component , Thus when they completed , Using Back Button it went Back to Search Page … Easy
But I created a notification
Initially that Notification went directly to the Maintenance Page , Worked. Problem there was no back to search page…..
SO I am trying to send the Search page … with the ID as a parameter ..
Thus if I see a parameter I go directly to Maintenance Page and Back Button SHOULD Show search Page But it does not.
I have tried a couple of things .. But it seems simple… transfer, viewurl etc… what am I missing .. or is it the placement I tred pre and post display
The search page N_RNAVM_MAIN should have a button/link which the users click to go to the Maintenance Component, correct?
Delete- Use the RowInit event of that field.
- In the RowInit, check if your ID parameter exists.
- If it does, then execute the same code that you execute on the FieldChange to navigate to the Maintenance page.
This should work in theory. If you are still running into issues, try using %Response.RedirectURL(...);
I found the issue....
ReplyDeleteI was using GenerateComponentContentURL to create the URL and then View it. Thus it was a direct transfer
I changed GenerateComponentPortalURL ... And the flow works out well Search page directly to Maintenance page , And the Back Button is setup to go back to search component
And with a small tweak
Local array of array of string &l_arrStrQueryParas = CreateArray(CreateArray("N_RESTART", "Y"));
SetTransferAttributes( False, True, "Interface list", "", &l_arrStrQueryParas);
Since the Back Button takes me back with all the parameters (Initial ID that was used to transfer to detail) , I added a flag it to reset and ignore the send to maintenance
Great! Thank you for sharing.
DeleteHi Sasank,
ReplyDeleteWe Just upgraded on PT 8.60.15.
We are facing back button issue on the header.
In the upgraded version there is only image coming coming on the back button there is not Description on the back button.
We want image and description on the back button.
can you please help.
Hi Rakesh - I am not sure what the issue is here. I encourage you to create a SR and work with Support. They will help troubleshoot.
ReplyDelete