I want to load data to datatable when commandButton pressed in primefaces. When page load first, the datatable must be empty but after clicked the commandButton, the datatable must be loaded! How can I do. I'm newbie at the primefaces.
From what you described in your question, here is a sample (This is just a working sample of what #Manuel described). Since the List on the backing bean is empty, at initial render, the datatable will be empty. When you click the commandbutton, it will fire the doPopulateList() method. This method will then populate the list. Finally, the update attribute will cause the datatable to reload the list from the backing bean. This time the List will be populated with 4 records.
<h:body>
<h:form>
<p:dataTable id="fooTable" value="#{dataTableBean.dataTableList}" var="record">
<p:column><h:outputText value="#{record}"/></p:column>
</p:dataTable>
<p:commandButton value="Populate DataTable" actionListener="#{dataTableBean.doPopulateList()}" update="fooTable"/>
</h:form>
</h:body>
DataTableSample backing bean:
#ManagedBean
#ViewScoped
public class DataTableBean implements Serializable {
List<String> dataTableList = new ArrayList<String>();
/**
* #return the dataTableList
*/
public List<String> getDataTableList() {
return dataTableList;
}
/**
* #param dataTableList the dataTableList to set
*/
public void setDataTableList(List<String> dataTableList) {
this.dataTableList = dataTableList;
}
public void doPopulateList(){
dataTableList.add("Record1");
dataTableList.add("Record2");
dataTableList.add("Record3");
dataTableList.add("Record4");
}
}
Don't initialize your dataTable value when the page loads at first. After that you can update p:dataTable
by updating it's id. Just add
<p:dataTable id="dataTableId" ...>
<p:commandButton update="dataTableId" ..>
to your commandButton. In addition you need to use either an
action="#{bean.addStuffToDataTable}"
or
actionListener="#{bean.addStuffToDataTable}"
as an attribute in your p:commandButton in order to populate data in your dataTable. Be sure to read Differences between action and actionListener before you use one of these attributes.
Related
I have multiple checkboxes - they are given the same id, "choosen" in the xhtml view code.
I have added an Ajax event listener for them, like so:
<ui:repeat var="posts"
value="#{postBacking.postsOverview.posts}">
<h:selectBooleanCheckbox id="choosen"
styleClass="check-margin"
value="#{posts.choosen}" rendered="#{posts.declined =='No'}">
<f:ajax listener="#{postsBacking.isPostsChosen}" event="click" render="#form" execute="#form"/>
</h:selectBooleanCheckbox>
</ui:repeat>
In the listener method in my backingBean, I would like to check if any of these checkboxes are checked, and then set a button disabled if no checkboxes are marked - and enabled if one or more is set.
But how do I get hold of the values of all checkboxes - can I use the AjaxBehaviorEvent objet for that or is there some other way?
While processing the ajax event listener, the checkbox values should normally have been applied to your data model where you can look up the state of user choice. Depending on that state, simply toggle a boolean bean property which disables the command button:
#Named
#ViewScoped
public class MyBean implements Serializable {
private List<Post> posts;
private boolean buttonDisabled = true;
public void ajaxEventListener(BehaviorEvent e) {
boolean anythingChosen = false;
for (Post post : posts) {
if (post.isChosen() && "No".equals(post.getDeclined())) {
anythingChosen = true;
break;
}
}
// or alternatively using the stream api:
// anythingChosen = posts.stream().filter(Post::isChosen).map(Post::getDeclined)
// .anyMatch("No"::equals);
setButtonDisabled(!anythingChosen);
}
// getters, setters ...
}
Using the following form, the command button is disabled as long as no checkbox is checked:
<h:form>
<ui:repeat var="post" value="#{myBean.posts}">
<h:selectBooleanCheckbox value="#{post.chosen}">
<f:ajax event="click" listener="#{myBean.ajaxEventListener}" render="#form" execute="#form"/>
</h:selectBooleanCheckbox>
</ui:repeat>
<h:commandButton action="#{myBean.doSomething()}" value="doSomething"
disabled="#{myBean.buttonDisabled}" />
</h:form>
You can use valueChangeListener rather than using listener and event attributes. The valueChangeListener will be triggered every time you check/uncheck the checkbox.
To get hold of the values when thevalueChangeListener is invoked, you can loop through the postBacking.postsOverview.posts to see if any value is checked.
Don't forget to update the button on <f:ajax render="#form btnId"/> to enable/ disable it.
I know that the primefaces picklist only alows transfer event like
<p:ajax event="transfer" listener="#{bean.onTransfer}" />
But I am looking for an onTargetSelected event. Is there a way to simulate it?
I thought about a JQuery function bound with a click event but I don't know on which element. I saw that when I select a line in the target list, the class of the li is transforming to ui-state-highlight. Is there a way to detect class changing with JQuery?
To call a bean method when the event will be fired, I thought about primefaces remoteCommand to send the ID of my object.
Do you have an idea about this event?
Note: I saw that there is a select with the target values in the source code but the selected value is 'selected' for each item and I don't know if there is something to do with this.
Thanks for your help
I have a trick. I am using this JQuery function :
$(document).ready(function(){
$('.ui-picklist-target .ui-picklist-item td').click(function() {
var id = $(this).closest("li").attr("data-item-value");
$('[id$=selectedItemId]').val(id); // Setting the value of my hidden input
updateSelectedTarget(); // Calling the remoteCommand function
});
});
I have added this to my xhtml page
<h:form>
...
<p:pickList ...>
</p:pickList>
<h:inputHidden id="selectedItemId" value="#{modifierUOBean.selectedTargetId}"/>
<p:remoteCommand name="updateSelectedTarget" actionListener="#{modifierUOBean.onSelectedTarget}"/>
</h:form>
And the bean:
private int selectedTargetId; // and getters and setters
public void onSelectedTarget() {
// Do what you want with selectedTargetId which contains the id of selected item
}
lets start simple:
- an easy search form
- two h:selectOneMenu components are declared inside a form
- the second selectOneMenu, is refreshed base on selecting an item of the first selectOneMenu (with ajax)
For this, i use a central Bean in request scope, because the two selectOneMenus are declared on many other pages, so i dont need to define the two following methods multiple times:
pageSupport:
#SuppressWarnings("unchecked")
public List<BranchenRubrik> getLst_branchenRubrik() {
if(lst_branchenRubrik == null) {
Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
this.lst_branchenRubrik = session.createQuery("from BranchenRubrik").list();
tx.commit();
}
return lst_branchenRubrik;
}
// Loading Subkats with parameter
#SuppressWarnings("unchecked")
public List<BranchenRubrikSub> getBranchenRubrikSub(long p_parent) {
List<BranchenRubrikSub> lst_branchenRubrikSub = new ArrayList<BranchenRubrikSub>();
if(p_parent > 0) {
Session session = hibernate.InitSessionFactory.getInstance().getCurrentSession();
Transaction tx = session.beginTransaction();
lst_branchenRubrikSub = session.createQuery("from BranchenRubrikSub BRS WHERE BRS.parentRubrik.id = :p1").setLong("p1",p_parent).list();
tx.commit();
}
return lst_branchenRubrikSub;
}
VDL:
<p:selectOneMenu value="#{searchBean2.fvz.branchenRubrikID}">
<f:selectItem itemLabel="Bitte wählen" itemValue="0"/>
<f:selectItems value="#{pageSupport.lst_branchenRubrik}" var="rubrik" itemValue="#{rubrik.id}" itemLabel="#{rubrik.rubrik}"/>
<f:ajax render="uiBranchenSubKat"/>
</p:selectOneMenu>
<h:outputText value="Unterkategorie" />
<p:selectOneMenu id="uiBranchenSubKat" value="#{searchBean2.fvz.branchenRubrikSubID}">
<f:selectItems value="#{pageSupport.getBranchenRubrikSub(searchBean2.fvz.branchenRubrikID)}" var="brs" itemLabel="#{brs.rubrik}" itemValue="#{brs.id}"/>
</p:selectOneMenu>
this works fine, i can submit the form and all data are saved and will be re-displayed.
Now, i want to include an h:panelGroup with binding to a methode, which build a pagination menue.
If i include the h:panelGroup binding="#{searchBean2.paginationMenu}"/> then, i cant submit the form, because it says that the value for the second h:selectOneMenu is not valid.
if i remove the "h:panelGroup binding" all working as expected.
The h:panelgroup can also binded to an empty methode "return new HtmlPanelGroup()"
then, the error occurs again.
looks like, that the component binding, breaks some validation.
thanks for your time
What's the difference between the following two pieces of code - with regards to listener placement?
<h:selectOneMenu ...>
<f:selectItems ... />
<f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>
and
<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
<f:selectItems ... />
</h:selectOneMenu>
The valueChangeListener will only be invoked when the form is submitted and the submitted value is different from the initial value. It's thus not invoked when only the HTML DOM change event is fired. If you would like to submit the form during the HTML DOM change event, then you'd need to add another <f:ajax/> without a listener(!) to the input component. It will cause a form submit which processes only the current component (as in execute="#this").
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
When using <f:ajax listener> instead of valueChangeListener, it would by default executed during the HTML DOM change event already. Inside UICommand components and input components representing a checkbox or radiobutton, it would be by default executed during the HTML DOM click event only.
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
Another major difference is that the valueChangeListener method is invoked during the end of the PROCESS_VALIDATIONS phase. At that moment, the submitted value is not been updated in the model yet. So you cannot get it by just accessing the bean property which is bound to the input component's value. You need to get it by ValueChangeEvent#getNewValue(). The old value is by the way also available by ValueChangeEvent#getOldValue().
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
// ...
}
The <f:ajax listener> method is invoked during INVOKE_APPLICATION phase. At that moment, the submitted value is already been updated in the model. You can just get it by directly accessing the bean property which is bound to the input component's value.
private Object value; // +getter+setter.
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value); // Look, (new) value is already set.
}
Also, if you would need to update another property based on the submitted value, then it would fail when you're using valueChangeListener as the updated property can be overridden by the submitted value during the subsequent UPDATE_MODEL_VALUES phase. That's exactly why you see in old JSF 1.x applications/tutorials/resources that a valueChangeListener is in such construct been used in combination with immediate="true" and FacesContext#renderResponse() to prevent that from happening. After all, using the valueChangeListener to execute business actions has actually always been a hack/workaround.
Summarized: Use the valueChangeListener only if you need to intercept on the actual value change itself. I.e. you're actually interested in both the old and the new value (e.g. to log them).
public void changeListener(ValueChangeEvent event) {
changeLogger.log(event.getOldValue(), event.getNewValue());
}
Use the <f:ajax listener> only if you need to execute a business action on the newly changed value. I.e. you're actually interested in only the new value (e.g. to populate a second dropdown).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
If you're actually also interested in the old value while executing a business action, then fall back to valueChangeListener, but queue it to the INVOKE_APPLICATION phase.
public void changeListener(ValueChangeEvent event) {
if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return;
}
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
System.out.println(newValue.equals(value)); // true
// ...
}
for the first fragment (ajax listener attribute):
The "listener" attribute of an ajax tag is a method that is called on the server side every time the ajax function happens on the client side. For instance, you could use this attribute to specify a server side function to call every time the user pressed a key
but the second fragment (valueChangeListener) :
The ValueChangeListener will only be called when the form is submitted, not when the value of the input is changed
*you might like to view this handy answer
First of all, my beans are managed by spring not by JSF and I am using custom view scope as described in this article. So if the behavior is weird for regular JSF2 and might be related to Spring, please tell me.
Bean:
public class DepartmentBean {
private DefaultTreeModel model;
public void preRender(ComponentSystemEvent event) throws Exception {
if (model == null) {
model = myService.buildModel();
}
}
public String clear() {
// resetting stuff
return "pretty:";
}
}
View:
<h:form>
<ice:panelGroup styleClass="crud-links">
<h:commandLink value="Delete" action="#{department.deleteDepartment}" />
</ice:panelGroup>
</h:form>
<h:form>
<ice:panelGroup>
<ice:tree id="tree" value="#{department.model}" var="item" hideRootNode="false" hideNavigation="false" imageDir="./xmlhttp/css/xp/css-images/">
<ice:treeNode>
<f:facet name="content">
<ice:panelGroup style="display: inline">
<ice:commandLink value="#{item.userObject.text}"></ice:commandLink>
</ice:panelGroup>
</f:facet>
</ice:treeNode>
</ice:tree>
</ice:panelGroup>
</h:form>
When page is loaded for first time the model object is populated with data, but when clicking delete button I notice that after clearing preRender() method is executed and the model (which was populated before clearing becomes null, and gets populated again, although I am in same page, and it should maintain the value)
Does the code have a problem that leads to such behavior, or this is the normal behavior?
If the problem maybe related to Spring or the custom view scope or the IceFaces, please advise.
UPDATE- REQUIREMENT:
I want to initialize the tree model on construction of the page, and while i am still on the page the tree model doesn't gets initialized again until i do that programatically .
oh my mistake, initialization should be inside #PostConstruct.