I have an h:selectOneMenu set up that looks something like this:
<f:view>
<h:form id="tehForm">
<h2>Header</h2><br/>
<a4j:outputPanel id="msgPanel" ajaxRendered="true">
<h:messages styleClass="message"/>
</a4j:outputPanel>
<a4j:outputPanel id="mainPanel" ajaxRendered="true"><br/>
Select an item:<br/>
<h:selectOneMenu id="itemMenu" value="#{bean.itemId}">
<f:selectItem itemValue="-1" itemLabel="Please Select..."/>
<s:selectItems value="#{bean.item}" itemValue="#{item.id}" var="item" label="#{item.name}"/>
<a4j:support event="onchange" action="#{bean.selectItem}"/>
</h:selectOneMenu>
<rich:spacer width="10px"/>
<a4j:commandLink value="Create New" action="#{bean.createNew}"
rendered="#{bean.selectedItemId != 0}"/>
<h:outputText rendered="#{bean.selectedItemId gt -1}" value="Item Name: "/><br/>
<h:inputText rendered="#{bean.selectedItemId gt -1}" value="#{bean.selectedItem.name}" maxlength="50" size="75"/><br/><br/>
<a4j:commandButton value="Save New" action="#{bean.save}" rendered="#{bean.selectedItemId == 0}"/>
<a4j:commandButton value="Save Changes" action="#{bean.save}" rendered="#{bean.selectedItemId gt 0}" oncomplete="jsRerender();" />
<a4j:jsFunction name="jsRerender" rerender="mainPanel"/>
</a4j:outputPanel>
</h:form>
</f:view>
When creating new items, the new item does show up in the drop-down, but if I change the "name" attribute of my item and save, the label doesn't change to the new name until after the next request, despite the data in the bean having changed.
So I worked around it by forcing a second call to rerender again when saving changes is complete. The trouble is, this rerenders the messages panel as well, so I nuke any messages that may have been displayed. Using limitToList="true" in the a4j:jsFunction has the same effect as not calling it.
I need suggestions; either a new target for the rerender function, or another way of approaching the problem. Thanks in advance!
Try removing the oncomplete javascript and using reRender="mainPanel":
<a4j:commandButton value="Save Changes"
action="#{bean.save}"
rendered="#{bean.selectedItemId gt 0}"
reRender="mainPanel" />
In your version I think that "Save Changes" button without reRender attribute will rerenders all the page, thus refreshing the messages.
Related
I would like to display in a dialog the number inserted in the inputText.
<p:inputText id="nbr"
type="number"
value="#{MB.number}"
required="true"
label="nbr" />
<p:confirmDialog id="confirmPurchase"
message="Your Database was successfully created. And contains "
appendToBody="true"
header="Buy Emails List"
severity="info"
widgetVar="purchase">
<a class="boldtext">
#{MB.number}
<h5> datas</h5>
</a>
<p:commandButton id="confirm" value="Buy" actionListener="#{MB.buy())}" />
<p:commandButton id="decline"
value="Decline"
onclick="purchase.hide();"
type="button" />
</p:confirmDialog>
The code below returns always 0 as a number in the confirm dialog.
Update1
the dialog is showing once the action in the commandButton is completed
<p:commandButton value="Extract" update="table nbr" id="ajax" ajax="true" widgetVar="extractButton action="#{MB.search()}" oncomplete="purchase.show();"/>
First of all, you need a <h:form/> around your <p:inputText> and your <p:commandButton>.
Your <p:commandButton> should have the attribute update=":outputUserText".
Inside your Dialog, you need a <p:outputLabel id="outputUserText" value="#{MB.number}"
I want to change my ActionListener of commandButton depending on the icon selected in advance:
<p:dialog id="dialog" header="Add Memo" widgetVar="dialogMemo" resizable="false" >
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="commentInput" value="Comment:" />
<p:inputTextarea id="commentInput" value="#{dashboardBean.getCurrentComment()}" rows="6" cols="25" label="commentInput"/>
<p:watermark for="commentInput" value="Enter your memo..."/>
<h:outputLabel for="selectShare" value="Share Memo: " />
<p:selectBooleanCheckbox id="selectShare" />
<h:outputLabel for="choosePriority" value="Priority:" />
<p:selectOneMenu id="choosePriority" value="#{dashboardBean.currentPriority}" label="choosePriority">
<f:selectItem itemLabel="Low Priority" itemValue="1" />
<f:selectItem itemLabel="Medium Priority" itemValue="2" />
<f:selectItem itemLabel="High Priority" itemValue="3" />
</p:selectOneMenu>
<p:commandButton id="submitDialog" icon="ui-icon-check" value="Confirm" ajax='false' type="submit" action="#{dashboardBean.getLastMemo()}"/>
<p:commandButton icon="ui-icon-close" onclick="dialogMemo.hide();" value="Cancel"/>
</h:panelGrid>
</h:form>
</p:dialog>
<p:layout fullPage="true">
<p:layoutUnit id="leftPanel" position="west" size="250" header="My Memos" resizable="false" closable="false" collapsible="false">
<h:form id="form">
<p:commandButton id="addMemo" icon="ui-icon-plus" onclick="dialogMemo.show();" type="submit" action="#{dashboardBean.getEditControl}"/>
<p:dashboard id="dashboardId" model="#{dashboardBean.model}" binding="#{dashboardBean.dashboard}">
</p:dashboard>
</h:form>
</p:layoutUnit>
</h:body>
When i click to command button (id="addMemo"), i want to change actionListener to commandButton(id="submitDialog").
I try that with:
public void getEditControl()
{
UIViewRoot view = _context.getViewRoot();
CommandButton button = (CommandButton) view.findComponent("submitDialog");
System.out.println("I am ID ==== [ " + button.getId() +" ]");
}
But 'button.getId()' does't work.
But 'button.getId()' does't work.
I gather that this is because the button is actually null and therefore the attempt to invoke the getId() method threw a NullPointerException? It's surprising that you stated the problem like that, "button.getId() doesn't work" instead of like "view.findComponent() returned null" (which has in turn the pretty obvious consequence that any attempt to access it would throw NullPointerException). If you had indeed no clue why it threw NullPointerException, then I strongly recommend to take a JSF pause and learn basic Java first.
Coming back to the concrete problem, the findComponent will return null when the client ID submitDialog doesn't exist in the component tree. Indeed, you have it inside a <h:form> which is a NamingContainer component. The button's client ID is more likely formId:submitDialog where formId is the ID of the button's parent form which you have to assign yet. An easy way to find out it is checking the ID of the generated HTML representation of the button.
See also this related question: How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar" Just substitute "ajax" in the answer with findComponent.
I am not sure that the way you do this is the right way.
If you want to get component instance better way to do this will be not get it by id but add
<p:commandButton id="submitDialog" icon="ui-icon-check"
value="Confirm" ajax='false' type="submit"
action="#{dashboardBean.getLastMemo()}" binding="#{dashboardBean.component}" />
and that way the property in the bean will always have the component instance that you need.
Note that the scope of bean where you put component binding should be view to avoid side affects.
when i click on the command button. validate method is getting called but the error message is not getting displayed..
here is my code..
<h:form id="form">
<h:body>
<p:panel style="width:500px">
<h:outputLabel for="year" value="Select Year: *" style="font-weight:bold" />
<p:selectOneMenu id="year" value="#{leaveBean.year}">
<f:selectItem itemLabel="Select One" itemValue="null" />
<f:selectItems value="#{leaveBean.yearDTO}" var="currentUser" itemValue="#{currentUser.name}" itemLabel="#{currentUser.name}" />
<f:validator validatorId="LeaveCardValidator" />
</p:selectOneMenu>
</p:panel>
<p:commandButton value="Submit" action="#{leaveController.leaveCard}" update="updateList,updateDetails" id="button"/>
<h:message for="year" style="color:red"/>
You seem to expect that JSF auto-updates the <h:message> on every ajax request. This is untrue. Perhaps you're confusing with PrimeFaces <p:messages> or <p:growl> which have each an autoUpdate attribute which enables you to tell them to auto-update themselves on every ajax request.
You really need to make sure that the <h:message> is covered by the ajax update. Just give it an ID
<h:message id="yearMessage" ... />
and include it in the client ID collection of the ajax update
<p:commandButton ... update="updateList updateDetails yearMessage" />
An alternative would be to replace <h:message> by <p:messages autoUpdate="true">.
Not sure where are the updateList and updateDetails are located but in the example give above you should use update="#form" instead or in addtion like this:
update="updateList updateDetails #form"
so that the form will be rendered again...
just use one of these :
update the whole form in order to update the content of
<h:message />
<p:commandButton value="Submit" action="#{leaveController.leaveCard}" update="#form" id="button"/>
or give the <h:message /> an id and id this id to the <p:commandButton/>
<h:message id="msg" for="year" style="color:red"/>
<p:commandButton value="Submit" action="#{leaveController.leaveCard}" update="updateList,updateDetails,msg" id="button"/>
I have a popup panel (id=PanelAddQueryCriteria) define on top of jsf page but it only enable it after user select a menu item (id=entityKind) and re-render take pace for that popupPanel. However because of that re-render, select item (id=queryCriteriaAttr) inside that popup panel don't trigger change listener (#{ceaDBBean.queryCriteriaAttrChanged}) in first value change, and only trigger when select again... Any help? Here the code:
<rich:popupPanel id="PanelAddQueryCriteria">
<h:form id="formAddQueryCriteria">
<h:selectOneMenu id="queryCriteriaAttr"
value="#{ceaDBBean.queryCriteriaAttr}" required="true"
valueChangeListener="#{ceaDBBean.queryCriteriaAttrChanged}">
<f:selectItems value="#{ceaDBBean.ceaEntityKindAttrs}"/>
</h:selectOneMenu>
</h:form>
</rich:popupPanel>
<h:panelGrid id="searchPanel">
<h:selectOneMenu id="entityKind"
value="#{ceaDBBean.entityKind}" required="true"
valueChangeListener="#{ceaDBBean.entityKindChanged}">
<a4j:ajax event="valueChange" render="addQueryCriteria" execute="#this" />
<f:selectItems value="#{ceaDBBean.ceaEntityKinds}" />
</h:selectOneMenu>
<a4j:commandLink styleClass="no-decor" id="addQueryCriteria"
render="PanelAddQueryCriteria"
disabled="#{empty ceaDBBean.entityKind}"
execute="#this" action="#{ceaDBBean.initAddQuryCriteria}"
oncomplete="#{rich:component('PanelAddQueryCriteria')}.show()">
<h:graphicImage id="addQueryCriteriaImg"
value="/images/icons/common/new.gif" width="16" height="16"
alt="#{adminMsg.addQueryCriteria}" />
<rich:tooltip value="#{adminMsg.addQueryCriteria}" for="addQueryCriteria" />
</a4j:commandLink>
</h:panelGrid>
Short answer: this problem is caused by JSF issue 790. Change
render="PanelAddQueryCriteria"
by
render="formAddQueryCriteria"
or maybe, if you have actually more into the panel which needs to be updated than the form itself,
render="PanelAddQueryCriteria formAddQueryCriteria"
Long answer: read following related questions:
<a4j:commandbutton> action is only invoked on second click
h:commandButton/h:commandLink does not work on first click, works only on second click
I am trying to submit values in a pop-up panel inside another panel that has a submit/action event. But before opening pop-up panel I need to invoke a function on my managed bean that create a new entity object. The outer panel has the only h:form, since you can't nest them. I have wrapped the pop-up panel in a a4j:region to submit only this part when the use submits the values inside the pop-up panel. This works, but not the execution of the preparing function that need to be invoked when the pop-up panel executes. I have tried a4j:commandLink but that component don't work together with the rich:popupPanel (strange since both of them are Richfaces components?!). So I have to relay on the h:commandLink and use ajax.
How can I invoke a function on my managed bean when the link to open/render the pop-up panel fires?
(What is the correct pattern for this?)
PS. The initial question has changed, but not the problem concerning submitting values in a pop-up panel.
Part of the xhtml file:
<h.form>
...
<a4j:region>
<rich:popupPanel id="popup_sys_user_req" modal="false" autosized="true" resizeable="false">
<f:facet name="header">
<h:outputText value="Request New Sector/Category" />
</f:facet>
<f:facet name="controls">
<h:outputLink value="#"
onclick="#{rich:component('popup_sys_user_req')}.hide(); return false;">
X
</h:outputLink>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Request New:" />
<h:selectOneMenu id="sys_req_type" value="#{userController.selectedSysUserRequest.sysrequesttype}" required="true" >
<f:selectItems value="#{userController.getSysRequestTypeItems('SECTOR_CATEGORY')}">
</f:selectItems>
</h:selectOneMenu>
<h:outputLabel value="Description:" />
<h:inputTextarea id="user_req_desc" value="#{userController.selectedSysUserRequest.description(desc)}" required="true" requiredMessage="Decription is missing" />
</h:panelGrid>
<a4j:commandButton action="#{userController.CreateSysUserRequest()}" value="Send Request" execute="sys_user_req_form" oncomplete="#{rich:component('popup_sys_user_req')}.hide(); return false;"/>
</rich:popupPanel>
</a4j:region>
</h:form>
The commandLink (re-edit)
<h:commandLink actionListener="#{userController.prepareCreateSysRequest}" value="Request New Sector/Category">
<f:ajax execute="popup_sys_user_req #this" render="popup_sys_user_req">
<rich:componentControl id="popup_ctr" event="click" target="popup_sys_user_req" operation="show"/>
</f:ajax>
</h:commandLink>
----------------------------
//Managed Bean:
public void prepareCreateSysRequest(ActionEvent event ) {
selectedSysUserRequest = new Sysuserrequest();
JsfUtil.log("Prepare Create System User Request");
}
This post continues the dicussion about the pop-up panel.
Greetings Chris.
If I understand correctly you want to submit all form elements inside popupPanel but not outside the panel when you invoke someAction1? I can think of two ways to do this:
1. a4jcommandButton has a limitToList attribute, you can list which components you want to be updated on the server
2. create your popupPanel outside of the first form and then use its own form:
<h:form>
...
<a4j:commandButton action="someAction2"...
</h:form>
<rich:popupPanel>
<h:form>
...
<a4j:commandButton action="someAction1"...
</h:form>
</rich:popupPanel>
Update
If you are using RichFaces 4 you can replace the limitToList attribute with limitRender
The problem is that the popup isn't a child of the form in jsf, you only need to use the domElementAttachment attribute to change that. So your code would look like this:
<h.form>
...
<a4j:region>
<rich:popupPanel id="popup_sys_user_req" modal="false" autosized="true" resizeable="false" domElementAttachment="form">
<f:facet name="header">
...