Гость
Форумы / Java [игнор отключен] [закрыт для гостей] / JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов / 11 сообщений из 11, страница 1 из 1
06.08.2019, 15:44
    #39845913
Aghial
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
Добрый день

Столкнулся с проблемой, при реализации на Primefaces с версиями <jsf.version>2.2.8</jsf.version> <primefaces.version>3.0</primefaces.version> динамического добавления и удаления компонентов inputTextarea с редактированием внутри них значений

В итоге удалось реализовать более менее работающий макет, но столкнулся с трудностью- при редактировании значения - если тут же не убирая фокус добавить новый элемент - подтягивается предыдущее нередактированное значения. Приложил скрин с описанием проблемы

Создал репо, в котором текущий код можно легко запустить используя mvn clean install run:jetty
https://github.com/aradess/jsf-jetty-dyn

Собственно вопрос, - каким должен быть код, чтобы редактирования и последующая вставка нового значения проходила корректно?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core">

<h:head>
    <title>PrimeFaces Hello World Example</title>
</h:head>

<h:body>
    <h:form>
        <p:panel id="main">
            <h:panelGrid columns="2">
                <h:outputText value="Add value"
                              style="vertical-align: top; width: 200px;"/>
                <p:selectOneMenu
                        widgetVar="type" id="type"
                        style="width: 350px"
                        value="#{helloWorld.selectedType}">
                    <f:selectItem itemValue="#{null}" itemLabel=""/>
                    <f:selectItems value="#{helloWorld.availableFields}" var="def" itemLabel="#{def}" itemValue="#{def}"/>
                    <p:ajax event="change"
                            update="main"
                            listener="#{helloWorld.change(helloWorld.selectedType)}"/>/>
                </p:selectOneMenu>
            </h:panelGrid>
            <h:panelGroup id="panelRepeatWrapper">
                <c:forEach id="panelRepeat" items="#{helloWorld.selectedFields}" var="field">
                    <h:panelGrid columns="3">
                        <h:outputText value="#{field}"
                                      style="vertical-align: top; width: 200px;"/>
                        <h:inputTextarea value="#{helloWorld.values[field]}"
                                         style="width: 550px; height: 50px;"/>
                        <p:commandButton value="x" action="#{helloWorld.onDelete(field)}" update="main">
                        </p:commandButton>
                    </h:panelGrid>
                </c:forEach>
            </h:panelGroup>
        </p:panel>
    </h:form>
</h:body>
</html>



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
package groupid;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@ManagedBean
@SessionScoped
public class HelloWorld {
    private final static List<String> ENTITIES = Arrays.asList(new String[]{"1", "2", "3", "4", "5"});

    @PostConstruct
    public void init() {
        selectedFields = ENTITIES.stream().filter(s -> !"5".equals(s)).collect(Collectors.toSet());
        availableFields = ENTITIES.stream().filter(s -> "5".equals(s)).collect(Collectors.toSet());
        values.put("1", "1");
        values.put("2", "2");
        values.put("3", "3");
        values.put("4", "4");
    }

    private String selectedType = "";
    private Set<String> availableFields;
    private Set<String> selectedFields;
    private Map<String, String> values = new HashMap<String, String>();

    public Set<String> getAvailableFields() {
        return availableFields;
    }

    public void setAvailableFields(Set<String> availableFields) {
        this.availableFields = availableFields;
    }

    public Set<String> getSelectedFields() {
        return selectedFields;
    }

    public void setSelectedFields(Set<String> selectedFields) {
        this.selectedFields = selectedFields;
    }

    public Map<String, String> getValues() {
        return values;
    }

    public void setValues(Map<String, String> values) {
        this.values = values;
    }

    public void change(String type) {
        Optional<String> f = availableFields.stream().filter(s -> s.equals(type)).findFirst();
        selectedFields.add(f.get());
        availableFields.remove(f.get());
        values.put(f.get(), null);
    }

    public void onDelete(String type) {
        Optional<String> f = selectedFields.stream().filter(s -> s.equals(type)).findFirst();
        selectedFields.remove(f.get());
        availableFields.add(f.get());
        values.put(f.get(), null);
    }

    public String getSelectedType() {
        return selectedType;
    }

    public void setSelectedType(String selectedType) {
        this.selectedType = selectedType;
    }
}
...
Рейтинг: 0 / 0
06.08.2019, 15:49
    #39845914
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
попробуй ui:repeat из facelets вместо c:forEach из jstl. Но я сильно не вчитывался, просто знаю что c:orEach хреновенько работает с динамически добавляемыми элементами
...
Рейтинг: 0 / 0
06.08.2019, 15:52
    #39845918
vas0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
JSTL по моему вообще не работает и вмести с JSF их лучше не использовать
...
Рейтинг: 0 / 0
06.08.2019, 17:09
    #39845978
Aghial
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
забыл никпопробуй ui:repeat из facelets вместо c:forEach из jstl. Но я сильно не вчитывался, просто знаю что c:orEach хреновенько работает с динамически добавляемыми элементами

пробовал ui:repeat - работоспособного варианта не получилось, то есть с c:forEach удалось продвинуться дальше, но попробую
...
Рейтинг: 0 / 0
06.08.2019, 17:12
    #39845982
Aghial
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
vas0,

совет по использованию JSTL был найден на stackoverflow, в то же время там была найден пост о различиях https://stackoverflow.com/questions/3342984/jstl-in-jsf2-facelets-makes-sense

Проблема в том, что я практически не работал ранее с JSF и не хотелось бы собирать все его грабли
Потому и прошу совета
...
Рейтинг: 0 / 0
07.08.2019, 15:09
    #39846406
Aghial
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
Попробовал ui:repeat
https://github.com/aradess/jsf-jetty-dyn/blob/feature/repeat/src/main/webapp/helloworld.xhtml
https://github.com/aradess/jsf-jetty-dyn/blob/feature/repeat/src/main/java/groupid/HelloWorld.java

Как бы работает, но это не то что нужно. Это все реализовано через события вида onclick=submit() - но это приводит к ререндерингу всей формы. А реальный кейс, в котором используется данная функциональность - сложнее, и ререндеринг в нем лишний.

Попробую уточнить загвоздку, которую нужно решить, которая есть в следующем коде:

Нужно чтобы при выборе значения в selectOneMenu и соответственно запуска в ajax listener="#{helloWorld.change(helloWorld.selectedType)}"/> , чтобы перед запуском этого listener значения которые введены в h:inputTextarea были синхронизированы с helloWorld.values[field]

Потому что сейчас наблюдается ситуация:
1) Ввели значение в Поле 3 (и это никак не отобразилось на значениях в helloWorld.values)
2) Выбрали добавление элемента из выпадающего списка
3) Обновили элемент c id="main" значениями которые в helloWorld.values (а они устаревшие)

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core">

<h:head>
    <title>PrimeFaces Hello World Example</title>
</h:head>

<h:body>
    <h:form>
        <p:panel id="main">
            <h:panelGrid columns="2">
                <h:outputText value="Add value"
                              style="vertical-align: top; width: 200px;"/>
                <p:selectOneMenu
                        widgetVar="type" id="type"
                        style="width: 350px"
                        value="#{helloWorld.selectedType}">
                    <f:selectItem itemValue="#{null}" itemLabel=""/>
                    <f:selectItems value="#{helloWorld.availableFields}" var="def" itemLabel="#{def}" itemValue="#{def}"/>
                    <p:ajax event="change"
                            update="main"
                            listener="#{helloWorld.change(helloWorld.selectedType)}"/>/>
                </p:selectOneMenu>
            </h:panelGrid>
            <h:panelGroup id="panelRepeatWrapper">
                <c:forEach id="panelRepeat" items="#{helloWorld.selectedFields}" var="field">
                    <h:panelGrid columns="3">
                        <h:outputText value="#{field}"
                                      style="vertical-align: top; width: 200px;"/>
                        <h:inputTextarea value="#{helloWorld.values[field]}"
                                         style="width: 550px; height: 50px;"/>
                        <p:commandButton value="x" action="#{helloWorld.onDelete(field)}" update="main">
                        </p:commandButton>
                    </h:panelGrid>
                </c:forEach>
            </h:panelGroup>
        </p:panel>
    </h:form>
</h:body>
</html>
...
Рейтинг: 0 / 0
07.08.2019, 18:53
    #39846596
Alexander A. Sak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
AghialНужно чтобы при выборе значения в selectOneMenu и соответственно запуска в ajax listener="#{helloWorld.change(helloWorld.selectedType)}"/> , чтобы перед запуском этого listener значения которые введены в h:inputTextarea были синхронизированы с helloWorld.values[field]


Давно не трогал JSF, но вдруг угадаю.
Добавить у p:ajax атрибут process="main" не пробовали? Вроде по умолчанию процессится только компонент, в котором расположен этот p:ajax.
...
Рейтинг: 0 / 0
21.08.2019, 22:07
    #39852397
olegeos
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
А что такая старая версия primefaces?
...
Рейтинг: 0 / 0
21.08.2019, 23:44
    #39852423
olegeos
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
 
            <p:panel id="main2">
                <h:panelGrid  columns="2">
                    <h:outputText value="Add value"
                                  style="vertical-align: top; width: 200px;"/>
                    <p:selectOneMenu 
                        widgetVar="type" id="type2"
                        style="width: 350px"
                        value="#{helloWorld.selectedType}">
                        <f:selectItem  itemLabel=""/>
                        <f:selectItems value="#{helloWorld.availableFields}" var="def" itemLabel="#{def}" itemValue="#{def}"/>
                        <p:ajax event="change"
                                update="main2"
                             listener="#{helloWorld.change2()}"/>/>
                    </p:selectOneMenu>
                </h:panelGrid>
                <p:panel id="panelRepeatWrapper2">

                    <ui:repeat id="panelRepeat1" value="#{helloWorld.listTextArea}" var="field" >
                        <h:panelGrid columns="4">
                            <h:outputText value="#{field.nomerRow}"
                                          style="vertical-align: top; width: 200px;"/>
                            <h:inputTextarea value="#{field.area}"
                                             style="width: 550px; height: 50px;"/>
                            <p:commandButton id="button1" value="x" actionListener="#{helloWorld.onDelete2(field)}"  update="form1:panelRepeatWrapper2"  />
                            <p:message  for="button1" showDetail="true" showSummary="true"/>
                        </h:panelGrid>

                    </ui:repeat>

                </p:panel>
            </p:panel>



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
public class HelloWorld {

    private final static List<String> ENTITIES = Arrays.asList(new String[]{"1", "2", "3", "4", "5"});

    private final String[] array = new String[]{"1", "2", "3", "4", "5"};
    private List<TestList> listTextArea;

    @PostConstruct
    public void init() {
        selectedFields = ENTITIES.stream().filter(s -> !"5".equals(s)).collect(Collectors.toSet());
        availableFields = ENTITIES.stream().filter(s -> "5".equals(s)).collect(Collectors.toSet());
        values.put("1", "1");
        values.put("2", "2");
        values.put("3", "3");
        values.put("4", "4");
        //----------
        listTextArea = new ArrayList<>();

    }

    private String selectedType = "";
    private Set<String> availableFields;
    private Set<String> selectedFields;
    private Map<String, String> values = new HashMap<>();

    public Set<String> getAvailableFields() {
        return availableFields;
    }

    public void setAvailableFields(Set<String> availableFields) {
        this.availableFields = availableFields;
    }

    public Set<String> getSelectedFields() {
        return selectedFields;
    }

    public void setSelectedFields(Set<String> selectedFields) {
        this.selectedFields = selectedFields;
    }

    public Map<String, String> getValues() {
        return values;
    }

    public void setValues(Map<String, String> values) {
        this.values = values;
    }

    public void change(String type) {
        Optional<String> f = availableFields.stream().filter(s -> s.equals(type)).findFirst();
        selectedFields.add(f.get());
        availableFields.remove(f.get());
        values.put(f.get(), null);
    }

    public void onDelete(String type) {
        Optional<String> f = selectedFields.stream().filter(s -> s.equals(type)).findFirst();
        selectedFields.remove(f.get());
        availableFields.add(f.get());
        values.put(f.get(), null);
    }

    public void change2() {
        TestList ttt = new TestList();
        ttt.setNomerRow("1");
        ttt.setArea(selectedType);
        listTextArea.add(ttt);
    }

    public void onDelete2(TestList test) {
        if (!listTextArea.isEmpty()) {
            listTextArea.remove(test);
            System.out.println(listTextArea.size());
        }
    }

    public String getSelectedType() {
        return selectedType;
    }

    public void setSelectedType(String selectedType) {
        this.selectedType = selectedType;
    }

    public List<TestList> getListTextArea() {
        return listTextArea;
    }

    public void setListTextArea(List<TestList> listTextArea) {
        this.listTextArea = listTextArea;
    }


такой вариант
...
Рейтинг: 0 / 0
26.08.2019, 00:16
    #39853611
Aghial
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
olegeosА что такая старая версия primefaces?

Прощу прощения за столь поздний ответ.
Потому что это суровый legacy с кучей функциональности и без тестов. Поменять версию компонентов нереально
...
Рейтинг: 0 / 0
26.08.2019, 02:00
    #39853616
Aghial
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов
olegeosтакой вариант

К сожалению у меня не взлетел. Были ошибки компиляции, исправил их, выложил код
https://github.com/aradess/jsf-jetty-dyn/blob/feature/2/src/main/webapp/helloworld.xhtml
По-прежнему была трабла:
1) Ввели новое значение в Поле 3 (и это никак не отобразилось на значениях в helloWorld.values)
2) Выбрали добавление элемента из выпадающего списка
3) После автоматического обновления значение в Поле 3 - старое, до редактирования

Нашел, путем неоднократного гугления по разным запросам следующий пост
https://stackoverflow.com/a/30216301

Предлагается использовать ajax и перехватывать значения в bean непосредственно из AjaxBehaviorEvent, и синхронизировать значение мапы в bean со значением, которое на экране
Вроде бы заработало, буду смотреть дальше

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
    public void fieldValue(AjaxBehaviorEvent e) {
        if (e.getSource() instanceof UIInput) {
            UIInput input = (UIInput) e.getSource();
            Object value = input.getValue();
            String id = input.getId();
            values.put(id.substring(2), value.toString());
        }
    }


https://github.com/aradess/jsf-jetty-dyn/tree/feature/AjaxBehaviorEvent
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / JSF, PrimeFaces - динамическое добавление, редактирование и удаление элементов / 11 сообщений из 11, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]