У меня большая проблема с моим интерфейсом Primefaces. Я хочу сделать цикл по списку и отобразить некоторую информацию + скрытое поле редактирования.
Коды XHTML Primefacesnippet:
<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>
Как я могу установить динамический идентификатор для panelGrid, чтобы обновить его с помощью commandButton click, если я хочу отредактировать этот div? + Как я могу переключить div во время его редактирования? или есть другие решения? Мне не разрешено использовать JavaScript / jQuery.
Большое тебе спасибо!
ваше здоровье, JohnRamb0r
Привет, спасибо за ответ. span был просто примером, чтобы показать, что это «решение» работает, а часть panelGrid - нет. Мне нужна визуализированная опция для обновления panelGrid, поэтому я хотел ее использовать.
Одна из проблем - разместить идентификатор (обновления) в компоненте, который имеет атрибут визуализации. Если этот компонент не отображается, вы не можете использовать идентификатор. Как я уже писал: вы должны разместить panelGrid внутри <h:panelGroup id='edit_#{data.id}'>, и никакие другие не должны иметь такой же идентификатор.
Теперь я удалил тег span и заключил свою панель PanelGrid в panelGroup. Вывод также такой же: Cannot find component for expression "edit_1" referenced from "main:j_idt70:0:j_idt122". Оператор обновления ищет "edit_1", но идентификатор панели создается Primefaces: "main: j_idt70: 0: edit_". Но я хочу, чтобы у panelGrid был такой же идентификатор -> edit_1 для примера.
Да, это внутри dataList. Поскольку dataList сам генерирует идентификаторы :0, вам не нужно использовать динамические идентификаторы. Просто используйте, например, editbox. Он будет изменен на main:j_idt70:x:editbox, где x - индекс строки в dataList. Его должен найти родственник update='editbox' без :.
да, но у меня есть много данных для отображения, и у всех данных есть одно скрытое «поле редактирования». Итак, если я позвоню update = "editbox", то все поля редактирования появятся - я прав?
Нет, только один в том же наминконтейнер.





Я бы сказал, что вы почти работаете против JSF и того, как он работает в вашем примере кода. Прежде чем показать вам рабочий пример, я хотел бы сказать здесь несколько вещей, связанных с передовой практикой:
data.locked будет автоматически переведена на вызов data.isLocked(). Вызов data.locked является предпочтительным, так как он заставит платформу оценивать его, а не отправлять уже оцененное значение.on<Something> при именовании методов, которые получают пользовательские события. Это позволяет четко их идентифицировать.Я сделал небольшой рабочий пример вашего кода (здесь используются Ломбок и 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;
}
}
Приведенный выше код инициализирует список данных из десяти сущностей и заполняет его случайными данными. Я воспользовался привилегией заменить data на entity. Когда дело доходит до вашего HTML-кода, я чувствовал, что он нуждается в некоторой очистке. Определение JSF могло бы выглядеть примерно так;
<?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>
Обратите внимание, как редактируемый div/outputPanel обернут в другой контейнер (форму). Если бы мы пропустили обертывание и вместо этого поместили обновление непосредственно в обернутый контейнер, тег rendered контейнера никогда не будет обновлен во время обновления, и поэтому div никогда не появится. В данном конкретном случае именно поэтому форма определяется вне контейнера, а не внутри.
В этом примере используется bean-компонент @ViewScoped, поэтому, пока вы остаетесь на странице, данные резервного копирования должны оставаться неизменными. Если вы перезагрузите страницу, вы получите новый набор данных с новыми сущностями, так как это повторно инициализирует компонент поддержки и вызовет @PostConstruct снова.
Смотрите также
И вы не можете генерировать динамические идентификаторы во время рендеринга (да и в этом редко бывает необходимость)
JSF уже делает это по умолчанию. Компонент всегда получает идентификатор "...sub-sub-component:sub-component:component". Кроме того, при использовании простых шрифтов вы действительно можете воспользоваться преимуществами селекторов JQuery внутри ваших атрибутов update - иногда это может значительно упростить задачу. Однако в этом случае вам даже не нужно ни о чем думать. Всегда следуйте принципу KISS, en.wikipedia.org/wiki/KISS_principle
Я также хотел бы добавить, что, поскольку связанный Q / A (stackoverflow.com/questions/9147771/…) к этому вопросу отвечает, вы действительно можете использовать JSTL (который работает во время сборки) для генерации идентификаторов. Но в этом конкретном случае, пожалуйста, не делайте этого.
В вашем примере вы создадите повторяющиеся идентификаторы
edit_{data.id}. Может в этом проблема. Вы получаете сообщения об ошибках? Если вам нужен идентификатор только дляupdate=, вы должны поместить<spanи<p:panelGridв<h:panelGroup id='edit_#{data.id}'>и удалить их идентификаторы.