I have a remmoteCommand that updates a List, after the items are loaded a repeat render selectBooleanCheckbox. However, the values are not correctly set at the checkbox, all of them are unchecked beside there are some items with selected property (which is Boolean) set to true.
If I just set an Item in the backing bean after the list is loaded it works only for that Item. What could be the problem?
index.xhtml
<h:form>
<h:panelGroup id="itemsHolder">
<h:panelGrid rendered="#{backingBean.items != null}">
<h:selectBooleanCheckbox value="#{backingBean.item.selected}" disabled="#{backingBean.rendered}" /> #{backingBean.item.name}
<ui:repeat value="#{backingBean.items.toArray()}" var="option" >
<h:selectBooleanCheckbox value="#{option.selected}" disabled="#{backingBean.rendered}" />
#{option.name}
<br />
</ui:repeat>
</h:panelGrid>
</h:panelGroup>
<p:remoteCommand rendered="#{backingBean.rendered}"
name="initItems"
actionListener="#{backingBean.initItems()}"
process="#this"
update="itemsHolder"/>
</h:form>
<ui:fragment rendered="#{backingBean.rendered}">
<script>
$(document).ready(function () {
setTimeout(function () {
initItems();
}, 3000);
});
</script>
</ui:fragment>
BackingBean.java
#Component
#ManagedBean
#Scope("view")
public class BackingBean {
private boolean rendered = true;
private Set<Item> items;
private Item item;
public void initItems() {
items = new LinkedHashSet<>();
items.add(new Item("item 1", true, "1"));
items.add(new Item("item 2", false, "2"));
items.add(new Item("item 3", true, "3"));
item = new Item("lonely item", true, "4");
}
//Getters and setters
}
UPDATE:
I created a copy of the real code in a SandBox, I am still not able to reproduce, I think I will have to add more dependencies from real code.
I've recreated your case and it is working just fine with following simple managed bean
#ManagedBean(name = "bean")
#ViewScoped
public class YourBean implements Serializable {
List<YourItem> items=new ArrayList<>();
YourItem anItem=new YourItem();
#PostConstruct
public void init() {
System.out.println("Bean is created");
//initialize items
anItem.setSelected(false);
//add 5 items to list
for (int i=0;i<5;i++){
YourItem item=new YourItem();
item.setSelected(false);
items.add(item);
}
}
public void onUpdateItems(){
System.out.println("Items will be updated...");
anItem.setSelected(true);
//modify 1st and 3rd item
items.get(0).setSelected(true);
items.get(2).setSelected(true);
//remove 4th item
items.remove(3);
}
public List<YourItem> getItems() {
return items;
}
public void setItems(List<YourItem> items) {
this.items = items;
}
public YourItem getAnItem() {
return anItem;
}
public void setAnItem(YourItem anItem) {
this.anItem = anItem;
}
}
p:command should be implemented on following way
<h:form id="form">
<h:panelGroup id="itemHolder">
<h:panelGrid rendered="#{bean.items != null}">
<h:selectBooleanCheckbox value="#{bean.anItem.selected}" />
<ui:repeat value="#{bean.items}" var="item">
<h:selectBooleanCheckbox value="#{item.selected}" />
#{item.selected}
<br />
</ui:repeat>
</h:panelGrid>
</h:panelGroup>
<p:remoteCommand name="startUpdate"
actionListener="#{bean.onUpdateItems()}"
update=":form:itemHolder"/>
<p:commandButton value="Update items" onclick="startUpdate();"/>
</h:form>
Compare your code with this example. Very probably there is problem in your managed bean method for updating items List or with the way how you are updating h:panelGroup.
Related
I have a bean with a List<T>:
#Named
#ViewScoped
public class Bean {
private List<Item> items;
private String value;
#Inject
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public void submit() {
System.out.println("Submitted value: " + value);
}
public List<Item> getItems() {
return items;
}
}
And I'd like to edit the value property of every item:
<h:form>
<ui:repeat value="#{bean.items}" var="item">
<h:inputText value="#{bean.value}" />
</ui:repeat>
<h:commandButton action="#{bean.submit}" />
</h:form>
With this code the value doesn't contain all the submitted values, only the latest submitted value. I also tried <c:forEach> and <h:dataTable>, but it didn't made any difference.
What should I do for collecting all the submitted values?
Your problem is caused because you're basically collecting all submitted values into one and same bean property. You need to move the value property into the bean behind var="item".
<h:form>
<ui:repeat value="#{bean.items}" var="item">
<h:inputText value="#{item.value}" /> <!-- instead of #{bean.value} -->
</ui:repeat>
<h:commandButton action="#{bean.submit}" />
</h:form>
In the bean action method, simply iterate over items in order to get all submitted values via item.getValue().
public void submit() {
for (Item item : items) {
System.out.println("Submitted value: " + item.getValue());
}
}
I am trying to add a PrimeFaces <p:tab> dynamically. While adding the second tab I am getting the following exception:
"java.lang.IllegalStateException: Component ID tab0 has already been found in the view".
How can I solve this?
Here is the view code:
<h:form prependId="false">
<p:tabView id="tabview" dynamic="true" cache="false"
binding="#{testBean.tabView}"
activeIndex="#{testBean.activeTab}" >
<h:commandButton value="Close" action="#{testBean.removeTab}"/>
</p:tabView>
<h:commandButton value="Add Tab" action="#{testBean.addTab}"/>
</h:form>
Here is the bean code:
public String addTab() {
String tabId="tab"+id;
System.out.println("Gen Id: "+tabId);
tab = new Tab();
tab.setTitle("Title: "+tabId);
tab.setId(tabId);
System.out.println("Tab Id: "+tab.getId());
tabView.getChildren().add(id,this.tab);
id++;
return "tabtest.jsf";
}
public String removeTab() {
tabView.getChildren().remove(activeTab);
return "tabtest.jsf";
}
Don't manually create components if everything can just be done in the view. This construct will fail if the bean is in a broader scope than the request scope. See also e.g. Binding attribute causes duplicate component ID found in the view
Follow the showcase example "TabView with Model" which allows you to dynamically populate tabs via a sane model and <p:tabView value="..." var="..."> like as <ui:repeat>/<h:dataTable>.
E.g. this view
<h:form>
<p:tabView value="#{bean.tabs}" var="tab">
<p:tab title="#{tab.title}">
#{tab.content}
<p:commandButton value="Close" action="#{bean.remove(tab)}" update="#form" />
</p:tab>
</p:tabView>
<p:commandButton value="Add Tab" action="#{bean.add}" update="#form" />
</h:form>
with this controller
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private List<Tab> tabs;
#PostConstruct
public void init() {
tabs = new ArrayList<>();
}
public void add() {
tabs.add(new Tab("tab" + tabs.size(), "some content"));
}
public void remove(Tab tab) {
tabs.remove(tab);
}
public List<Tab> getTabs() {
return tabs;
}
}
and this model
public class Tab {
private String title;
private String content;
public Tab(String title, String content) {
this.title = title;
this.content = content;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
}
This is because same ID is being generated for new tab(The one which ur adding). To avoid this, append a variable to the id as
<p:tabView id="tabview_#{testBean.i}" dynamic="true" cache="false"binding="#{testBean.tabView}"
activeIndex="#{testBean.activeTab}" >
<h:commandButton value="Close" action="#{testBean.removeTab}"/>
</p:tabView>
I am able to render dynamic but don't know how to get those dynamically created values in back end.
test.xhtml
<h:form>
Insert Your Desire Number : <h:inputText value="#{bean.number}">
<f:ajax listener="#{bean.submitAjax}" execute="#form" render="#form" event="keyup" />
</h:inputText>
<br></br>
<h:outputText value="#{bean.text}" />
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}" />
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{item.submit}" />
</h:form>
If I render 3 input boxes, and when I submit the button i get the last value only, Can someone guide me how can i
Bean.java
#ManagedBean(name="bean")
#SessionScoped
public class Bean {
private int number;
private List<Item> items;
private Item item;
//getter and setter are omitted
public void submitAjax(AjaxBehaviorEvent event)
{
items = new ArrayList<Item>();
for (int i = 0; i < number; i++) {
items.add(new Item());
}
}
}
Item.java
private String value;
//getter and setter are omitted
public void submit() {
System.out.println("Form Value : "+value);
}
Your submit() method is in the wrong place. You should put it on the managed bean, not on the entity.
Thus so,
<h:commandButton value="Submit" action="#{bean.submit}" />
with
public void submit() {
for (Item item : items) {
System.out.println(item.getValue());
}
}
or more formally,
#EJB
private ItemService service;
public void submit() {
service.save(items);
}
I am trying to add a PrimeFaces <p:tab> dynamically. While adding the second tab I am getting the following exception:
"java.lang.IllegalStateException: Component ID tab0 has already been found in the view".
How can I solve this?
Here is the view code:
<h:form prependId="false">
<p:tabView id="tabview" dynamic="true" cache="false"
binding="#{testBean.tabView}"
activeIndex="#{testBean.activeTab}" >
<h:commandButton value="Close" action="#{testBean.removeTab}"/>
</p:tabView>
<h:commandButton value="Add Tab" action="#{testBean.addTab}"/>
</h:form>
Here is the bean code:
public String addTab() {
String tabId="tab"+id;
System.out.println("Gen Id: "+tabId);
tab = new Tab();
tab.setTitle("Title: "+tabId);
tab.setId(tabId);
System.out.println("Tab Id: "+tab.getId());
tabView.getChildren().add(id,this.tab);
id++;
return "tabtest.jsf";
}
public String removeTab() {
tabView.getChildren().remove(activeTab);
return "tabtest.jsf";
}
Don't manually create components if everything can just be done in the view. This construct will fail if the bean is in a broader scope than the request scope. See also e.g. Binding attribute causes duplicate component ID found in the view
Follow the showcase example "TabView with Model" which allows you to dynamically populate tabs via a sane model and <p:tabView value="..." var="..."> like as <ui:repeat>/<h:dataTable>.
E.g. this view
<h:form>
<p:tabView value="#{bean.tabs}" var="tab">
<p:tab title="#{tab.title}">
#{tab.content}
<p:commandButton value="Close" action="#{bean.remove(tab)}" update="#form" />
</p:tab>
</p:tabView>
<p:commandButton value="Add Tab" action="#{bean.add}" update="#form" />
</h:form>
with this controller
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private List<Tab> tabs;
#PostConstruct
public void init() {
tabs = new ArrayList<>();
}
public void add() {
tabs.add(new Tab("tab" + tabs.size(), "some content"));
}
public void remove(Tab tab) {
tabs.remove(tab);
}
public List<Tab> getTabs() {
return tabs;
}
}
and this model
public class Tab {
private String title;
private String content;
public Tab(String title, String content) {
this.title = title;
this.content = content;
}
public String getTitle() {
return title;
}
public String getContent() {
return content;
}
}
This is because same ID is being generated for new tab(The one which ur adding). To avoid this, append a variable to the id as
<p:tabView id="tabview_#{testBean.i}" dynamic="true" cache="false"binding="#{testBean.tabView}"
activeIndex="#{testBean.activeTab}" >
<h:commandButton value="Close" action="#{testBean.removeTab}"/>
</p:tabView>
I have a bean with a List<T>:
#Named
#ViewScoped
public class Bean {
private List<Item> items;
private String value;
#Inject
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public void submit() {
System.out.println("Submitted value: " + value);
}
public List<Item> getItems() {
return items;
}
}
And I'd like to edit the value property of every item:
<h:form>
<ui:repeat value="#{bean.items}" var="item">
<h:inputText value="#{bean.value}" />
</ui:repeat>
<h:commandButton action="#{bean.submit}" />
</h:form>
With this code the value doesn't contain all the submitted values, only the latest submitted value. I also tried <c:forEach> and <h:dataTable>, but it didn't made any difference.
What should I do for collecting all the submitted values?
Your problem is caused because you're basically collecting all submitted values into one and same bean property. You need to move the value property into the bean behind var="item".
<h:form>
<ui:repeat value="#{bean.items}" var="item">
<h:inputText value="#{item.value}" /> <!-- instead of #{bean.value} -->
</ui:repeat>
<h:commandButton action="#{bean.submit}" />
</h:form>
In the bean action method, simply iterate over items in order to get all submitted values via item.getValue().
public void submit() {
for (Item item : items) {
System.out.println("Submitted value: " + item.getValue());
}
}