Reputation: 1
I have a big problem with my Primefaces Interface. I want to do a loop over a list and display some information + a hidden editfield.
XHTML Primefaces codesnippet:
<p:dataList value="#{datas}" var="data">
<div class="ui-g">
<div class="ui-g-3">
<h2>#{data.desc}</h2>
</div>
<div class="ui-g-3">
<p:commandButton operation="edit" disabled="#{data.isLocked()}" actionListener="#{view.edit(data)}"
style="width:120px;" update="edit_#{data.id}" />
<p:commandButton operation="delete" actionListener="#{view.delete(data.getId())}" disabled="#{data.isLocked()}"/>
</div>
</div>
<!-- works perfectly to set the id -->
<span id="edit_#{data.id}">#{data.desc} #{index}</span>
<!-- doesnt work - maybe of the rendering moment to set the id? -->
<p:panelGrid id="edit_#{data.id}" rendered="#{view.edit}">
<p:outputLabel for="desc" value="#{msg.text}" />
<p:inputText id="desc" value="#{view.selectedValue.desc}" />
</p:panelGrid>
How can I set a dynamic ID to the panelGrid to update it by commandButton click if I want to edit that div? + How can I make the div toggled while editing it? or are there other Solutions? I am not allowed to use JavaScript/jQuery.
Thank you very much!
cheers, JohnRamb0r
Upvotes: 0
Views: 579
Reputation: 2321
I would say you are nearly working against JSF and the way it works in your code example. Before showing you a working example, there are a few things I would like to say here related to good practice:
data.locked
will be translated to a call to data.isLocked()
automatically. A call to data.locked
is preferred, as it will cause the framework to evaluate it instead of you sending in the already evaluated value.on<Something>
when naming methods that receive user events. This allows you to clearly identify them.I made a small working example of your code (this uses Lombok and Apache Commons);
@Data
@Named
@ViewScoped
public class DataListViewBackingBean implements Serializable {
private Entity entity;
private Entity selectedEntity;
private List<Entity> dataEntities;
@PostConstruct
private void init() {
dataEntities = new ArrayList<>();
for (int i = 0; i < 10; i++) {
dataEntities.add(new Entity(i, RandomUtils.nextBoolean(),
RandomStringUtils.randomAlphabetic(30)));
}
}
@Data
@AllArgsConstructor
@EqualsAndHashCode(exclude = {"locked","description"})
public class Entity {
private int id;
private boolean locked;
private String description;
}
public void onEdit(Entity entity) {
selectedEntity = entity;
}
public void onDelete(Entity entity) {
dataEntities.remove(entity);
selectedEntity = null;
}
}
The code above initializes a data list of ten entities and fills this with random data. I took the privilege to change data
to entity
. When it comes to your HTML code, I felt it needed some cleaning. The definition of the JSF would look something like this;
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Data list test</title>
</h:head>
<h:body>
<h:form id="items">
<p:dataList type="definition" value="#{dataListViewBackingBean.dataEntities}" var="entity">
<div class="ui-g">
<div class="ui-g-8">
#{entity.description}
</div>
<div class="ui-g-4" style="text-align: right">
<p:commandButton value="Edit" disabled="#{entity.locked}" action="#{dataListViewBackingBean.onEdit(entity)}" update=":edit" />
<p:commandButton value="Delete" disabled="#{entity.locked}" action="#{dataListViewBackingBean.onDelete(entity)}" update="@form :edit" />
</div>
</div>
</p:dataList>
</h:form>
<h:form id="edit">
<p:outputPanel rendered="#{dataListViewBackingBean.selectedEntity != null}">
<h1>Editing...</h1>
<p:inputText placeholder="Description" value="#{dataListViewBackingBean.selectedEntity.description}" />
<p:commandButton value="Save" update=":items" />
</p:outputPanel>
</h:form>
</h:body>
</html>
Note how the editing div/outputPanel
is wrapped in another container (a form). If we skipped the wrapping and instead pushed an update on the wrapped container directly, the rendered
tag of the container would never be updated during a refresh and the div would therefore never show up. In this particular case, this is why the form is defined outside the container instead of inside.
This example uses a @ViewScoped
bean, so as long as you stay on the page, the backing data should stay the same. If you reload the page you will get a new data set with new entities, as this will reinitialize a backing bean and call @PostConstruct
again.
See also
Upvotes: 2