This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 6 years ago.
I try to update component panelgroup after clicking on commandLink, but it doesn't succeed. I have already tryed many ways but nothing helps. Please, say me, what should I do that to update panelgroup?
<h:panelGroup layout="block" id="content">
<h:panelGroup layout="block" id="nav">
<h:form id="itemsMenu">
<h:commandLink value="View" update="workplace" actionListener="#{main.determineAction}">
<f:param name="link" value="Viewing telephone book"/>
</h:commandLink>
</h:form>
</h:panelGroup>
<h:panelGroup id="workplace">
<h:panelGroup layout="block" rendered="#{main.responseRendered}">
<ui:include src="#{main.linkPage}"/>
</h:panelGroup>
</h:panelGroup>
</h:panelGroup>
Bean code:
#ManagedBean(name = "main")
#ViewScoped public class MainBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> listItemsMenu;
private String linkPage;
private boolean responseRendered = false;
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(final boolean responseRendered) {
this.responseRendered = responseRendered;
}
public String getLinkPage() {
return linkPage;
}
public void setLinkPage(final String linkPage) {
this.linkPage = linkPage;
}
public void determineAction(final ActionEvent event) {
final Locale currentLocale = SessionBean.getCurrentLocale();
final MessageManager messageManager = new MessageManager(currentLocale);
final Map<String, String> mapParameters = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap();
final String linkType = mapParameters.get(Constants.ATTRIBUTE_LINK_TYPE);
if (linkType.equals(messageManager.getProperty(Constants.MESSAGE_MENU_VIEWING))) {
linkPage = Constants.PAGE_VIEW;
}
...
responseRendered = true;
}
}
Ok well command link doesn't have an attribute update, so that should have thrown an error here:
<h:commandLink value="View" update="workplace">
I'm assuming you want an ajax solution it would be:
<h:commandLink value="View">
<f:param name="link" value="Viewing telephone book"/>
<f:ajax render="workplace" listener="#{main.determineAction}" />
</h:commandLink>
Related
I want to update a <p:outputPanel id="personName"> inside a node of a tree using PrimeFaces AJAX update. I tried my approach both with PrimeFaces <p:tree> and OmniFaces <o:tree>. In both cases the nested <p:outputPanel> is not updated. Updating the whole tree works though. I think I assigned an id to all necessary elements.
To update the <p:outputPanel id="personName"> I nested a <p:autoUpdate on="person-change-event" />. The AutoUpdateTagHandler is picking up the <p:outputPanel> but the renderer is never called. Also, the updated <p:outputPanel id="personName"> is never part of the partial view response sent back to the client.
If I add the ids personTree or oTree to the update list of the command button it works. But I specifically want to update only parts of the node to save costs. What am I doing wrong?
I created a minimal working example which I will describe:
PrimeFaces tree:
<p:card id="personTreeCard">
<f:facet name="title">Persons (PrimeFaces)</f:facet>
<p:tree id="personTree"
var="person"
value="#{personTreeModel}">
<p:treeNode>
<p:outputPanel layout="inline" id="personId">
(<h:outputText value="#{person.dbId}"/>)
</p:outputPanel>
<p:outputPanel layout="inline" id="personName" styleClass="person-#{person.state}">
<h:outputText value="#{person.name}"/>
<p:autoUpdate on="person-change-event"/>
</p:outputPanel>
</p:treeNode>
</p:tree>
</p:card>
OmniFaces tree:
<p:card id="otherPersonTreeCard">
<f:facet name="title">Persons (OmniFaces)</f:facet>
<o:tree value="#{otherPersonTreeViewModel.root}" var="person" varNode="node" id="oTree">
<o:treeNode level="0">
<ul class="person-list">
<o:treeNodeItem id="personNode">
<li class="person-list-item">
<p:outputPanel layout="inline" id="oPersonId">
(<h:outputText value="#{person.dbId}"/>)
</p:outputPanel>
<p:outputPanel layout="inline" id="oPersonName"
styleClass="person-#{person.state}">
<h:outputText value="#{person.name}"/>
<p:autoUpdate on="person-change-event"/>
</p:outputPanel>
</li>
</o:treeNodeItem>
</ul>
</o:treeNode>
</o:tree>
</p:card>
I have a simple form that selects a Person and updates the name by appending a random number to the end:
<h:form id="personForm">
<p:card id="settingsCard">
<div class="ui-fluid p-formgrid p-grid">
<div class="p-field p-col-12">
<p:selectOneMenu id="personSelectOneMenu"
converter="omnifaces.SelectItemsConverter"
value="#{personFormViewModel.selectedPerson}">
<f:selectItems value="#{personSessionModel.personList}"
itemLabel="(#{person.dbId}) #{person.name}"
itemValue="#{person}"
var="person"/>
<f:selectItem noSelectionOption="true" itemLabel="-- select person --"/>
<p:ajax/>
</p:selectOneMenu>
</div>
<div class="p-field p-col-12">
<p:commandButton value="Change person"
update="#this #obs(person-change-event) #id(personName) personSelectOneMenu messages"
action="#{personFormAction.changePersonAction}"/>
</div>
</div>
</p:card>
</h:form>
Backing Beans:
#Model
public class PersonTreeModel extends RootTreeNode implements Serializable {
private static final long serialVersionUID = 454578540550974256L;
#Inject
private PersonSessionModel personSessionModel;
#PostConstruct
void onPostConstruct() {
final List<TreeNode> personTreeNodes = personSessionModel.getPersonList()
.stream()
.map(this::createPersonNode)
.collect(Collectors.toList());
this.setChildren(personTreeNodes);
}
private TreeNode createPersonNode(final Person person) {
final DefaultTreeNode personNode = new DefaultTreeNode(person);
this.addTreeNode(person.getDbId(), personNode);
return personNode;
}
}
#Slf4j
#Named
#ApplicationScoped
public class PersonSessionModel {
#Inject
private PersonService personService;
private static final int NUMBER_OF_PERSONS = 10;
#Getter
private List<Person> personList;
#PostConstruct
private void onPostConstruct() {
log.info("Creating {} persons", NUMBER_OF_PERSONS);
this.personList = personService.createPersons(NUMBER_OF_PERSONS);
}
}
#Getter
#Setter
#ViewModel
public class PersonFormViewModel implements Serializable {
private static final long serialVersionUID = -4933603892578811138L;
private Person selectedPerson;
}
#Action
public class PersonFormAction {
private static final Random RANDOM = new Random();
#Inject
private PersonFormViewModel viewModel;
#Inject
private PersonTreeModel treeModel;
public void changePersonAction() {
final Person selectedPerson = viewModel.getSelectedPerson();
if (selectedPerson.getState().equals("alive")) {
selectedPerson.setState("dead");
} else {
selectedPerson.setState("alive");
}
selectedPerson.setName(selectedPerson.getName() + " " + RANDOM.nextInt(10));
treeModel.onPostConstruct();
}
}
#ViewModel
public class OtherPersonTreeViewModel implements Serializable {
private static final long serialVersionUID = -5150070481006078761L;
#Getter
private TreeModel<Person> root;
#Inject
private PersonSessionModel personSessionModel;
#PostConstruct
private void onPostConstruct() {
root = new ListTreeModel<>();
personSessionModel.getPersonList().forEach(root::addChild);
}
}
I'm trying to set a dialog title at runtime (dynamically) but update with #widgetVar expression cannot do the trick. Any ideas?
The first command button renders the dialog with the dynamic title but the second command fail to render the title! Why? Here the example is simplified but the real page is more complex and it is difficult to specify the id of the dialog to render.
<h:form>
<p:commandButton value="Basic" ajax="true" process="#this"
update=":dlg1" oncomplete="PF('widget-dialog').show();"
actionListener="#{dialogView.changeTitle('Dynamic title')}" />
<p:commandButton value="Widget" ajax="true" process="#this"
update="#widgetVar('widget-dialog')"
oncomplete="PF('widget-dialog-1').show();"
actionListener="#{dialogView.changeTitle('Dynamic title')}" />
</h:form>
<p:dialog id="dlg1" header="#{dialogView.title}"
widgetVar="widget-dialog" dynamic="true">
<h:outputText value="Resistance to PrimeFaces is futile!!!" />
</p:dialog>
#ManagedBean(name = "dialogView")
#ViewScoped
public class DialogView {
private String title = null;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void changeTitle(String title) {
setTitle(title);
}
}
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>