JSF rendered attribute - jsf-2

I have a couple of panel groups, one with "register" and "log in" links, and the other with "log out". When I log in only the "log in" link disappears, the "register" stays rendered, and the "log out" never gets rendered. The #{user.loggedIn}" returns true when the user is logged in. And when refreshing the screen in debug mode I can see that method is being run. Any suggestions for how to get this to work correctly. The code should be explanatory, please let me know if it isn't.
<h:panelGroup rendered="#{!user.loggedIn}">
<li>
<h:outputLink id="loginLink" value="javascript:void(0)" onclick="dlg.show()" title="login" styleClass="loginpanelclass">Log In</h:outputLink>
</li>
<li>
<h:link value="Register" outcome="/registration/register.xhtml" />
</li>
</h:panelGroup>
<h:panelGroup rendered="#{user.loggedIn}">
<li>
<h:commandLink action="#{user.logout()}">Logout</h:commandLink>
</li>
</h:panelGroup>

The elements you want to reference have to be in a naming container if they are not in the same naming container you are referencing them from. For me I launch a login dialog using primefaces when the first link in my question is clicked. Inside the dialog is a form. When that form completes it tells the panels in my question above to render or not by using the p:dialog update attribute. I had to put the panels in my question inside a naming container and then was able to successfully reference them using the ':' notation through the hierarchy.
If anyone is having trouble look for articles on component hierarchies and naming containers in JSF. With the hints given by Daniel in his comments above and the stuff I found looking at hierarchies and naming containers I figured this one out good enough for now. Still a few uncertainties but my code does what I want it to do for now. :) I'm marking the answer Daniel gave in his linked question up by one.

Related

Capybara: click on text within <span>

I had a bot that would apply on indeed.com jobs. It would collect jobs then apply to them one by one. However, indeed recently made things a lot harder. Used to be able to just locate the button's id and use that but now the id is dynamic: changes from different job positions.
Does anyone know how it is possible to link to the "Apply Now" button (not really a botton) if the code below is:
<a class="indeed-apply-button" href="javascript:void(0);" id="indeed-ia-1532137767182-0">
<span class="indeed-apply-button-inner" id="indeed-ia-1532137767182-0inner">
<span class="indeed-apply-button-label" id="indeed-ia-1532137767182-0label">Apply Now</span>
<span class="indeed-apply-button-cm">
<img src="https://d3fw5vlhllyvee.cloudfront.net/indeedapply/s/14096d1/check.png" style="border: 0px;">
</span>
</span>
</a>
Many ways to click that element, the 3 simplest would probably be
click_link('Apply Now') # find link by partial text and click it
click_link(class: 'indeed-apply-button') # find and click link by class
find('span', text: 'Apply Now').click # find span by text and click in it
in my case I had to select an option shown using js-chosen library inside an iframe. So, its not a regular select tag. So had to do following to select:-
within_frame(find("#cci_form")) do
find('#showing_listing_id_chosen').click
find('[data-option-array-index="2"]').click
end
But, no luck using
find('.active-result[data-option-array-index="2"]').click
or
find('li[data-option-array-index="2"]').click

<ui:include> with dynamic src ... complete madness [duplicate]

This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 5 years ago.
I'm having a massive problem getting an extremely simple task done in JSF. The problem: I have objects, who have aggregated properties that can vary in type from object to object. Depending on the type of the property, I want to use a different set of input fields.
The subtype components reside in frameworks and get loaded on demand. To this end, I use the following code:
<h:panelGroup id="zusatzdaten">
<fieldset class="clear">
<legend>#{tickerUI.ticker.tickerDescription.label}
(#{tickerUI.ticker.tickerDescId})
</legend>
<h:panelGroup rendered="#{tickerUI.editComponentName != null}">
<ui:include src="#{tickerUI.editComponentName}"/>
</h:panelGroup>
</fieldset>
</h:panelGroup>
The name of the component comes out of TickerUI, which is of #SessionScope. Now the dazzling bit: when it first loads, the correct subcomponent is displayed. However, when using a link in the navigation, which should lead to including a different component, the content is NOT updated! This results in an error, because the data is now a different subtype, but the form components are still from the previous one.
When going back from the error and clicking the link again, the correct component is displayed. I logged the value of editComponentName and the correct values are returned. This is very confusing. Why is including the wrong content when the getter returns the correct component name to the 's src attribute?
Help greatly appreciated.
Actually your problem is a classic view build vs view render time problem/misunderstanding. More specifically, the view is built on every new request and reconstructed from a previously saved state on postbacks. Later the view is rendered to produce HTML content.
Now, as <ui:include> is a tag handler, or in official terms a view build time tag, when you first request the page, its value attribute is evaluated, and the included page makes its way into the view. Upon postback, contrary to what you might expect, the incuded contents are already there, in the reconstructed view. So, it is an expected behaviour that you'll have the exact part of view rendered.
As to the solution, you could just simply include an exhaustive list of static includes that are wrapped in conditionally rendered <ui:fragment> JSF components. For simplicity, all content could be places within a container like <h:panelGroup> that's always rendered for ease of AJAX updates. The code could be assembled as follows:
<h:panelGroup id="ui">
<ui:fragment rendered="#{bean.condition1}">
<ui:include src="/path/to/file1.xhtml"/>
</ui:fragment>
...
<ui:fragment rendered="#{bean.condition_n}">
<ui:include src="/path/to/file_n.xhtml"/>
</ui:fragment>
</h:panelGroup>
A classical dilemma, it seems. BalusC's blog gave the solution for my case in the form of a configuration parameter in web.xml:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>

nested ui:repeat issue (or f:ajax)

i have 2 ui:repeat nested like this:
<ui:repeat var="father" value="#{miuchile3.getMenusPadre(miuchile3.keyModulo)}" >
<li>
<h:commandLink value="#{father.nombre}" action="#{miuchile3.setMenu(father)}">
<f:ajax render=":menupags:menuDetalle" />
</h:commandLink>
<ul>
<ui:repeat var="submenu" value="#{miuchile3.getHijos(father.id)}" >
<li><h:commandLink value="#{submenu.nombre}" actionListener="#{miuchile3.setMenu(submenu)}">
<f:ajax render=":menupags:menuDetalle" />
</h:commandLink></li>
</ui:repeat>
</ul>
</li>
</ui:repeat>
this generate a menu with this format
father menu 1
son menu_1
son menu_2
father menu 2
son menu2_1
son menu2_2
son menu2_3
etc..
when i click in this submenus i use f:ajax to render a panelgroup with details of the selected menus (it shows the pages associated to them), the problem is that it only works properly for father menu 1 and its submenus, but for father menu 2, it works ok for its 2 first submenus, if there is a third submenu associated to "father menu 2" and i click on it, it doesn't do anything.
im not sure if it is a issue with the nested ui:repeat or with f:ajax, but i think ui:repeat stop working properly after the second iteration or something like that.. the "setMenu()" function (inside the nested ui:repeat) stop working for some reason. but it could be f:ajax too.. i dont really know.
EDIT:
now i found the issue but i dont know how to solve it yet.
the problem is that for the first iteration (frist menu and its submenus) the method im calling in the action "setMenu()" works ok, but for the second iteration (father menu 2, and its submenus) the setMenu() method is called only 2 times, if there are more than 2 submenus, the method im calling in the action (setMenu())doesn't work, i mean the iteration works because it prints all the names of the menus and submenus , but the action after the first iteration only works for 2 submenus.
i changed the ui:repeat for a datatable, and it worked as i wanted.. i would not recomment to use ui:repeat nested if you need to invoke some action inside, it has weird behavior.

p:commandlink inside ui:repeat

In our application we are displaying the menus dynamically. We have the menu object(menuitems in below code) populated with all the menu items (read from an xml). The home page then generates the menus by usinng ui:repeat. Insdie ui:repeat there are p:commandlink.
Below is the code
<h:form id="mainMenu">
<h:panelGroup id="MMPanel" layout="block" styleClass="left_menu">
<ui:repeat var="node" value="#{menuitems.level1menus}">
<p:commandLink immediate="true" styleClass="menu"
action="#{menuitems.onLevel1MenuChange(node.id)}"
update=":pageTitle :menuLevel2 :menuLevel3" title="#{node.name}"
rendered="#{menuitems.selectedLevel1.id!=node.id}" onclick="menuSelect(this)">
<span class="icon icon_#{node.name}"></span>
<span class="text">#{node.name}</span>
</p:commandLink>
<p:commandLink immediate="true" styleClass="menu activelink"
action="#{menuitems.onLevel1MenuChange(node.id)}"
update=":pageTitle :menuLevel2 :menuLevel3" title="#{node.name}"
rendered="#{menuitems.selectedLevel1.id==node.id}" onclick="menuSelect(this)">
<span class="icon icon_#{node.name}"></span>
<span class="text">#{node.name}</span>
</p:commandLink>
</ui:repeat>
</h:panelGroup>
</h:form>
The menuitems bean is at Session level.
There are two diffeent p:commandlink inside ui:repeat. The only difference between the 2 is in the styleclass and rendered attribute. This is done to identify the default menu item when the user logs for the first time and give it an extra css of "activeLink".
The java script called on onclick is given below (in case it is required)
function menuSelect(selectOne){
$(".left_menu>a").removeClass("activelink");
$(selectOne).addClass("activelink");
removeAllChannels();
}
function removeAllChannels(){
$.atmosphere.unsubscribe();
}
The removeAllChannels is to remove primepush autorefresh channels we have.
The issue i am facing is this.
All the links are getting rendered correctly and in Firebug i see all of them have the same html.
But the one which is generated with the extra css "activeLink" (through rendered condition -- menuitems.selectedLevel1.id==node.id) is not working. Nothing happens when i click this default link. All other links work fine.
So when i click on a different link, it takes me to the required page. But when i click back on the menu which was default, nothing happens
I added a Custom phase listener and saw that all the lifecyle stages are called when this link is clicked but the action method is not.
I went through the links this and this but could not figure out the issue.
Please help.
Do tell me if something is not clear
As part of safeguard against tampered/hacked requests, the JSF component's rendered attribute is re-evaluated during processing the form submit. In case of a command link/button, if it evaluates false, then its action won't be queued/invoked. This matches the symptoms you're seeing.
This can in turn happen if the managed bean #{menuitems} is request scoped and/or when the properties behind #{menuitems.level1menus} or #{menuitems.selectedLevel1} are incompatibly changed during the postback request.
Putting the bean in the view scope and ensuring that the getters do not do any business job should fix this problem.
See also:
How to choose the right bean scope?
commandButton/commandLink/ajax action/listener method not invoked or input value not updated - point 5 applies to you

How to disable development stage messages?

I like to know if it is posible disable the error messages that appear at the bottom of the page when I have some JSF syntax error:
<ul title="Project Stage[Development]: Unhandled Messages"
id="javax_faces_developmentstage_messages">
<li style="Color: orange">
The button/link/text component needs to have a Form in its ancestry. Please
add <h:form>.
</li>
</ul>
And you can't say "add the form tag".
Remove the <context-param> with name of javax.faces.PROJECT_STAGE from your web.xml, or set its value to Production instead of Development.
See also:
The form component needs to have a UIForm in its ancestry. Suggestion: enclose the necessary components within <h:form>

Resources