Tetapkan ID dalam daftar data secara dinamis tanpa JavaScript

Saya memiliki masalah besar dengan Antarmuka Primefaces saya. Saya ingin melakukan perulangan pada daftar dan menampilkan beberapa informasi + bidang edit tersembunyi.

Cuplikan kode XHTML Primefaces:

<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.

Terima kasih banyak!

bersorak, JohnRamb0r


person JohnRamb0r    schedule 10.01.2019    source sumber
comment
Dalam sampel Anda, Anda akan menghasilkan duplikat id edit_{data.id}. Mungkin ini masalahnya. Apakah Anda mendapatkan pesan kesalahan? Jika Anda memerlukan id hanya untuk update= Anda harus meletakkan <span dan <p:panelGrid di dalam <h:panelGroup id='edit_#{data.id}'> dan menghapus idnya.   -  person Holger    schedule 10.01.2019
comment
Hai, terima kasih atas jawaban Anda. span hanyalah sebuah contoh untuk menunjukkan bahwa solusi ini berfungsi dan bagian panelGrid tidak. Saya memerlukan Opsi yang diberikan untuk memperbarui panelGrid oleh karena itu saya ingin menggunakannya.   -  person JohnRamb0r    schedule 10.01.2019
comment
Salah satu masalahnya adalah, menempatkan id (perbarui) dalam sebuah komponen, yang memiliki atribut yang dirender. Jika komponen ini tidak dirender, Anda tidak dapat menggunakan id. Seperti yang saya tulis: Anda harus menempatkan panelGrid di dalam <h:panelGroup id='edit_#{data.id}'> dan tidak ada orang lain yang harus mendapatkan id yang sama.   -  person Holger    schedule 10.01.2019
comment
Sekarang saya menghapus tag span dan membungkus panelGrid saya di dalam panelGroup. Outputnya juga sama: Cannot find component for expression "edit_1" referenced from "main:j_idt70:0:j_idt122". Pernyataan pembaruan mencari edit_1 tetapi id panelgrid dihasilkan oleh Primefaces: main:j_idt70:0:edit_. Tapi saya ingin panelGrid memiliki id yang sama --› edit_1 sebagai contoh.   -  person JohnRamb0r    schedule 10.01.2019
comment
Uh, ya, itu ada di dalam dataList. Karena dataList menghasilkan id dengan sendirinya :0 Anda tidak perlu menggunakan id dinamis. Cukup gunakan yaitu editbox. Itu akan diubah menjadi main:j_idt70:x:editbox di mana x adalah indeks baris dari dataList. Seorang kerabat update='editbox' tanpa : harus menemukannya.   -  person Holger    schedule 10.01.2019
comment
ya tapi saya punya banyak data untuk Ditampilkan dan setiap data memiliki satu kotak edit tersembunyi. Jadi jika saya menelepon update="editbox"maka setiap kotak edit akan muncul - Benar kan?   -  person JohnRamb0r    schedule 10.01.2019
comment
Tidak, hanya yang ada di namincontainer yang sama.   -  person Kukeltje    schedule 10.01.2019


Jawaban (1)


Menurut saya, Anda hampir bekerja melawan JSF dan cara kerjanya dalam contoh kode Anda. Sebelum menunjukkan kepada Anda contoh kerja, ada beberapa hal yang ingin saya sampaikan di sini terkait dengan praktik yang baik:

  • Jangan memanggil metode secara langsung, gunakan terjemahan referensi properti bawaan. Referensi ke data.locked akan diterjemahkan menjadi panggilan ke data.isLocked() secara otomatis. Panggilan ke data.locked lebih disukai, karena akan menyebabkan kerangka kerja mengevaluasinya alih-alih Anda mengirimkan nilai yang sudah dievaluasi.
  • Bekerja dengan JSF - bukan menentangnya. Ada banyak id yang tidak perlu dan penggunaan tag dan indeks yang tidak diperlukan dalam kode contoh Anda. Tetap sederhana dan bekerja dengan kerangka kerja. Daripada mereferensikan id, mereferensikan objek secara langsung - ini menyederhanakan kode dan membuatnya lebih mudah digunakan pada halaman itu sendiri.
  • Gunakan tindakan sebagai pelaksana utama logika dan hasil bisnis. Pemroses tindakan dieksekusi sebelumnya dan dapat digunakan untuk mencegat atau menghentikan eksekusi tindakan utama. Oleh karena itu cocok digunakan sebagai langkah validasi sebelum mengeksekusi logika bisnis.
  • Tandai acara Anda. Merupakan praktik yang baik untuk menggunakan konvensi penamaan on<Something> saat memberi nama metode yang menerima peristiwa pengguna. Ini memungkinkan Anda mengidentifikasinya dengan jelas.

Saya membuat contoh kecil kode Anda (ini menggunakan Lombok dan 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;
    }
}

Kode di atas menginisialisasi daftar data sepuluh entitas dan mengisinya dengan data acak. Saya mengambil hak istimewa untuk mengubah data menjadi entity. Mengenai kode HTML Anda, saya merasa perlu dibersihkan. Definisi JSF akan terlihat seperti ini;

<?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>

Perhatikan bagaimana pengeditan div/outputPanel dibungkus dalam wadah lain (formulir). Jika kita melewatkan pembungkusan dan malah mendorong pembaruan pada wadah yang dibungkus secara langsung, tag rendered wadah tersebut tidak akan pernah diperbarui selama penyegaran dan oleh karena itu div tidak akan pernah muncul. Dalam kasus khusus ini, inilah sebabnya formulir didefinisikan di luar wadah, bukan di dalam.

Contoh ini menggunakan kacang @ViewScoped, jadi selama Anda tetap berada di halaman tersebut, data pendukungnya akan tetap sama. Jika Anda memuat ulang halaman, Anda akan mendapatkan kumpulan data baru dengan entitas baru, karena ini akan menginisialisasi ulang backing bean dan memanggil @PostConstruct lagi.

Lihat juga

person Adam Waldenberg    schedule 11.01.2019
comment
Dan Anda tidak dapat membuat id dinamis pada waktu render (juga jarang diperlukan) - person Kukeltje; 11.01.2019
comment
JSF sudah melakukan ini secara default. Sebuah komponen selalu mendapat ID "...sub-sub-component:sub-component:component". Selain itu, saat menggunakan primeface, Anda sebenarnya dapat memanfaatkan penyeleksi JQuery di dalam atribut update Anda - hal ini terkadang dapat membuat segalanya jauh lebih mudah. Namun, dalam hal ini, Anda bahkan tidak perlu memikirkan semua itu. Selalu ikuti prinsip KISS, en.wikipedia.org/wiki/KISS_principle - person Adam Waldenberg; 12.01.2019
comment
Saya juga ingin menambahkannya sebagai Tanya Jawab tertaut (stackoverflow.com/questions/9147771/) untuk jawaban pertanyaan ini, Anda sebenarnya dapat menggunakan JSTL (yang beroperasi selama waktu pembuatan) untuk menghasilkan ID. Namun untuk kasus penggunaan khusus ini, mohon jangan lakukan itu. - person Adam Waldenberg; 12.01.2019