How to open overlay menu from oncomplete of p:commandButton with Primefaces? - primefaces

I'm using Primefaces 3.3.1 and have question.
I have p:commandButton inside p:column of p:dataTable. I can show overlay menu when button is clicked with xhtml shown below.
<p:commandButton id="btnID" icon="ui-icon-circle-triangle-s" style="height: 16px;">
<f:setPropertyActionListener value="#{searchItem}" target="#{bean.selectedSearchItem}" />
</p:commandButton>
<p:slideMenu overlay="true" trigger="btnID" my="left top" at="left bottom"
model="#{bean.menuModel}"/>
In this case, bean.menuModel can return menu data instantly. But I have another case also which pre-procsessing is required to make menu data ready. So I have this one too.
<p:commandButton ajax="true" id="historyButton" action="#{bean.getHistory()}"
icon="ui-icon-note" style="height: 16px;"
onstart="workingDialog.show();"
oncomplete="workingDialog.hide(); historyMenu.show();">
<f:setPropertyActionListener value="#{searchItem}" target="#{bean.selectedSearchItem}" />
</p:commandButton>
<p:menu overlay="true" widgetVar="historyMenu" my="left top" at="left bottom"
model="#{searchBean.menuModel}"/>
What I meant is, when button is clicked, it calls bean.getHistory() which starts loading menu data for that row, and show modal dialog with circling icon. When loading is finished, dialog will go away and overlay menu will be shown. What I can't do is a last part of this scenario. Above code fires exception.
java.lang.NullPointerException
javax.faces.component.UIComponentBase.findComponent(UIComponentBase.java:561)
org.primefaces.component.menu.BaseMenuRenderer.encodeOverlayConfig(BaseMenuRenderer.java:138)
org.primefaces.component.menu.MenuRenderer.encodeScript(MenuRenderer.java:45)
org.primefaces.component.menu.BaseMenuRenderer.encodeEnd(BaseMenuRenderer.java:39)
javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1763)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1759)
Code shown below works fine, without menu related code.
<p:commandButton ajax="true" id="historyButton" action="#{searchBean.getHistory()}"
icon="ui-icon-note" style="height: 16px;"
onstart="workingDialog.show();"
oncomplete="workingDialog.hide();">
<f:setPropertyActionListener value="#{searchItem}" target="#{bean.selectedSearchItem}" />
</p:commandButton>
I guess this is easy question for experts. How can I open overlay menu from oncomplete?
Thanks in advance.

I could not find a solution for this issue but I came up with conclusion that what I wanted to do is not a good idea with the environment I'm working on.
First, I noticed that menu gets data from bean when row of data table is populated, not when menu is shown. And there is no lazy loading mechanism for menu. So button click -> get data for menu from server -> open menu cannot be done as I expected (at least it seems to me).
Second, I noticed putting menu in DataTable (under TabView in my case) causes very strange problem. When I update DataTable, some ajax related function stops working. I can't explain this problem to make you understand or believe, but app I'm working on is having this problem.
So, I gave up putting menu in DataTable in my app. Thank you for your attention.
I accept this answer not to lower my already LOW accept rate.

Related

VoiceOver focuses on aria-hidden element

On our (Vue.js v.2) webpage we have a section where you can swipe between cards, or by pressing "left" and "right" button. This swiping section is written with vanilla JS, and no fancy library. In order to have the adjacent visible when swiping, I need to have all of them visible in the DOM tree, but hiding them from the viewer. I have made it so all the unfocused cards are aria-hidden, and it works great when using ChromeVox. The problem is that when using VoiceOver, and I click the "right" button, and immediately tab down to the card, it will read out the card to the left, and also get trapped there since the card is aria-hidden. Code-wise the change from aria-visible to aria-hidden happens as soon as the button is pressed, but it seems like VoiceOver has already decided that when I am focusing on the "right" button, that the next element should be card 5 (for instance). If I wait around 1 or 2 seconds after clicking the "right" button, it will change the "next" element, and focus on the correct one (card 6) when I tab down. Is there any way to get around this, so it will focus only on the aria-visible element? Maybe a way to "force refresh" VoiceOver's stack of elements to read next? Maybe if I remove the message being read out when clicking the button, it will refresh immediately? I still haven't found of doing either of those things. I created a low quality flowchart to illustrate the problem better. What I want is for it to behave like ChromeVox.
I have tried several methods of getting this to work now, and it feels like it's a bug with VoiceOver. Some of the (desperate) attempts I've tried: setting tabindex=-1, role=presentation, changing the ID of "right" button dynamically as I navigate between cards, creating an empty div with a dynamic ID below the button, using aria-flowto, dynamically setting aria-describedby on the "next" element, and different variations between these and some other stuff I can't remember.
Eventually I found a solution that kinda works. I'm not very happy about it, but it's better than nothing. What I did was to make the title inside the card aria-hidden, and creating a currentHeader variable in store. I created an sr-only & aria-visible title above the swiping section, where the v-html points to the currentHeader variable. This way, the "next" element for the "right" button will always be the same element, but content will change after I click the button. It's not a perfect solution, and for some reason it makes VoiceOver "halt" when trying to go to the next element immediately after clicking the button, but at least the user won't read the wrong text and get trapped. Here's a pseudocode illustration of how I did it if my explaination was confusing:
// old solution // old swiping-section
<button id="left" /> <div v-for="element in elements" />
<button id="right" /> <h3 v-html="element.title" />
<swiping-section /> <p v-html="element.desc" />
</div>
// new solution // new swiping section
<button id="left" /> <div v-for="element in elements" />
<button id="right" /> <h3 aria-hidden="true" "v-html="element.title" />
<h3 class="sr-only" v-html="currentHeader" /> <p v-html="element.desc" />
<swiping-section /> </div>
If anyone finds a better way to do it, please post your solution.

2 mutual exclusively rendered command buttons in form, only 1 working

In my login.xhtml file I have 1 form. This form also contains 2 <p:commandButton> which are mutual exclusively rendered.
The actions point to 2 different methods defined in my LoginController Java-class.
When the command button with the loginController.login action is clicked, the corresponding method in my LoginController is called as exptected.
But when the command button with the loginController.resetpassword action is clicked, the corresponding method in my LoginController is not called. The LoginController is just being reloaded and then nothing else (attempt #1).
First, I thought it's because I cannot have 2 command buttons in the same form, even though only 1 of them is rendered at any time, but if I swap the actions of the two action buttons, then the loginController.resetpassword is being called (attempt #2)! It does not matter if I swap the lines of code, so the lines of codes with the command buttons are read in another order (attempt #3).
For some readon, it seems as if I can only get the command button with id=loginButton to work?
I do not use navigation in my faces-config.xml. The form element is of type <h:form>
What am I doing wrong? Java 8, Primefaces 6.1
Attempt#1: default code
<p:commandButton id="resetpasswordButton"
value="#{msg['reset_password']}"
action="#{loginController.resetpassword}"
rendered="${not empty param.pw_reset}"
/> <!-- #resetpasswordButton button does not work -->
<p:commandButton id="loginButton"
value="#{msg['login']}"
action="#{loginController.login}"
rendered="${empty param.pw_reset}"
/> <!-- #loginButton button works, calling login() -->
Attempt#2: actions switched
<p:commandButton id="resetpasswordButton"
value="#{msg['reset_password']}"
action="#{loginController.login}"
rendered="${not empty param.pw_reset}"
/> <!-- #resetpasswordButton button does not work -->
<p:commandButton id="loginButton"
value="#{msg['login']}"
action="#{loginController.resetpassword}"
rendered="${empty param.pw_reset}"
/> <!-- #loginButton button works, calling resetpassword() -->
Attempt#3: order switched
<p:commandButton id="loginButton"
value="#{msg['login']}"
action="#{loginController.login}"
rendered="${empty param.pw_reset}"
/> <!-- #loginButton button works, calling login() -->
<p:commandButton id="resetpasswordButton"
value="#{msg['reset_password']}"
action="#{loginController.resetpassword}"
rendered="${not empty param.pw_reset}"
/> <!-- #resetpasswordButton button does not work -->

Title rendering issue

I've implemented a p:commandButton to update the contents of a table when it is clicked. I think this is working (although It isn't properly tested) but the more immediate issue is as follows.
Bug
Before the request, the title bar looks like this:
And after I hit the refresh button on the right, the page re-renders as follows:
Attempts to solve
The following is the current code for my p:commandButton:
<p>
<p:commandButton oncomplete="eventFeedsDialog.show()" update=":eventFeedsForm" id="feedsRefresh" icon="ui-icon-refresh" title="Refresh page" style="height:40px; width:40px; float:right;">
<f:setPropertyActionListener value="#{true}" target="#{searchBean.refresh}"/>
</p:commandButton>
</p>
The eventFeedsDialog is the p:dialog element that this button is wrapped in, which is further wrapped in a h:form element. Here is the declaration of the eventFeedsDialog element:
<p:dialog id="eventFeedsDialog" header="Feeds" widgetVar="eventFeedsDialog" resizable="false" width="1000"
styleClass="dialog">
I've tried changing the oncomplete attribute to point at the h:form instead of the dialog, but it appears not to have worked. I thought up a hack, whereby I append a mountain of spaces in the header attribute, but that is horrendously ugly.
I've not found anything on google like this, so I was wondering if you guys have any ideas?

show full text on mouse over or hover on a <p:commandLink>

One of the table column displays commandLink in its rows, whose value is a long text. I am displaying only a portion of that text and when a user hovers on the link I want a pop up or something that will display the full text and hide it when the mouse is away.
How would I approach this, tried ajax event but didn't work.
Its
Thanks
In case anyone is wondering, this is what I did finally using tooltip...
<div id="sub" style="width:175px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;">
<p:commandLink id ="myLink" value="#{message.subject}" ajax="true"
update=":messageForm:grid">
<f:setPropertyActionListener value="#{message}"
target="#{myBean.selectedMessage}"/>
</p:commandLink>
<p:tooltip for="myLink" value="#{message.subject}" showEffect="slide" hideEffect="slide" style="background-color:#FFFFCC;border:1px dotted #000000;" />
</div>

Primefaces Dialogs Form Structure

I'm using Primefaces for a project and I'm seeing bad results with IE vs chrome/firefox/safari in regards to modal Primefaces dialog windows and I think it has to do with form placement. In IE these dialogs dont appear, but I can see the transparency. In chrome/firefox they're fine. What is the best practice for the below situations:
List item base xhtml page that has one form. This page has several
links that open up dialogs who have their own ajax submit
(commandButton, commandLink) events.
Should the dialog be located within or outside the base xhtml page's form?
Should the dialog have its own form?
Below is an illustration:
<html>
<ui:composition>
<ui:define name="content">
<h:form id="xyz">
//main page content here, commandButtons, commandLinks...etc
</h:form>
<dc:zoomDialog/>
</ui:define>
</ui:composition>
</html>
<!-- zoomDialog maps to the below -->
<html>
<ui:component>
<h:form id="dialogFrm">
<p:dialog widgetVar="zoomDlg" modal="true" styleClass="dialog dialog2"
draggable="false" resizable="false" showEffect="fade"
hideEffect="fade">
//dialog content here, commandButton, commanLink...etc
</p:dialog>
</h:form>
</ui:component>
I don't see it in your example code but some time ago I had a similar problem. The reason was: nested forms (the same symptoms as you describe: all browser work, except IE). Nested forms are not valid html. Some browsers can handle it. IE cannot.
A good test is to put the whole html outpout (browser source, not the jsf source) into the W3C Html validator and analyze the results.
In the Primefaces showcase the h:form element is always inside the p:dialog. See this discussion.