Установить идентификатор в списке данных динамически без JavaScript

У меня большая проблема с моим интерфейсом 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

В вашем примере вы создадите повторяющиеся идентификаторы edit_{data.id}. Может в этом проблема. Вы получаете сообщения об ошибках? Если вам нужен идентификатор только для update=, вы должны поместить <span и <p:panelGrid в <h:panelGroup id='edit_#{data.id}'> и удалить их идентификаторы.

Holger 10.01.2019 15:22

Привет, спасибо за ответ. span был просто примером, чтобы показать, что это «решение» работает, а часть panelGrid - нет. Мне нужна визуализированная опция для обновления panelGrid, поэтому я хотел ее использовать.

JohnRamb0r 10.01.2019 15:29

Одна из проблем - разместить идентификатор (обновления) в компоненте, который имеет атрибут визуализации. Если этот компонент не отображается, вы не можете использовать идентификатор. Как я уже писал: вы должны разместить panelGrid внутри <h:panelGroup id='edit_#{data.id}'>, и никакие другие не должны иметь такой же идентификатор.

Holger 10.01.2019 15:34

Теперь я удалил тег 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 для примера.

JohnRamb0r 10.01.2019 15:48

Да, это внутри dataList. Поскольку dataList сам генерирует идентификаторы :0, вам не нужно использовать динамические идентификаторы. Просто используйте, например, editbox. Он будет изменен на main:j_idt70:x:editbox, где x - индекс строки в dataList. Его должен найти родственник update='editbox' без :.

Holger 10.01.2019 16:00

да, но у меня есть много данных для отображения, и у всех данных есть одно скрытое «поле редактирования». Итак, если я позвоню update = "editbox", то все поля редактирования появятся - я прав?

JohnRamb0r 10.01.2019 16:37

Нет, только один в том же наминконтейнер.

Kukeltje 10.01.2019 17:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
319
1

Ответы 1

Я бы сказал, что вы почти работаете против JSF и того, как он работает в вашем примере кода. Прежде чем показать вам рабочий пример, я хотел бы сказать здесь несколько вещей, связанных с передовой практикой:

  • Не вызывайте методы напрямую, используйте встроенный перевод ссылок на свойства. Ссылка на data.locked будет автоматически переведена на вызов data.isLocked(). Вызов data.locked является предпочтительным, так как он заставит платформу оценивать его, а не отправлять уже оцененное значение.
  • Работа с JSF - не против. В вашем примере кода много ненужных идентификаторов и использования ненужных тегов и индексов. Будьте проще и работайте с фреймворком. Вместо ссылки на идентификатор, ссылки на объект напрямую - это упрощает код и упрощает использование на самой странице.
  • Используйте действие как главный исполнитель бизнес-логики и результата. Прослушиватели действий выполняются заранее и могут использоваться для перехвата или остановки выполнения основного действия. Поэтому они подходят для использования в качестве шага проверки перед выполнением бизнес-логики.
  • Отметьте свои события. Рекомендуется использовать соглашение об именах 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 снова.

Смотрите также

И вы не можете генерировать динамические идентификаторы во время рендеринга (да и в этом редко бывает необходимость)

Kukeltje 11.01.2019 19:32

JSF уже делает это по умолчанию. Компонент всегда получает идентификатор "...sub-sub-component:sub-component:component". Кроме того, при использовании простых шрифтов вы действительно можете воспользоваться преимуществами селекторов JQuery внутри ваших атрибутов update - иногда это может значительно упростить задачу. Однако в этом случае вам даже не нужно ни о чем думать. Всегда следуйте принципу KISS, en.wikipedia.org/wiki/KISS_principle

Adam Waldenberg 12.01.2019 03:09

Я также хотел бы добавить, что, поскольку связанный Q / A (stackoverflow.com/questions/9147771/…) к этому вопросу отвечает, вы действительно можете использовать JSTL (который работает во время сборки) для генерации идентификаторов. Но в этом конкретном случае, пожалуйста, не делайте этого.

Adam Waldenberg 12.01.2019 03:36

Другие вопросы по теме