Вкладка Primefaces tabview Событие Change, вызванное после отображения вкладки

Я работаю над проектом, используя Primefaces 3.5 и JSF2.1 (Mojarra).

Я создал простые лица <p:tabView id="tabsVw" dynamic="false"> с двумя вкладками внутри, и каждая вкладка имеет таблицу данных простых лиц.

 <h:form> 
        <p:tabView  dynamic="false">
        <p:ajax event="tabChange" listener="#{tstTab.onDtlTabChanged}" />

            <p:tab title="tab1">
                <p:dataTable value="#{tstTab.list1}" var="v1">
                    <p:column>
                        <h:outputText value="#{v1}"/>
                    </p:column>
                </p:dataTable>
            </p:tab>

            <p:tab title="tab2">
                <p:dataTable value="#{tstTab.list2}" var="v2">
                    <p:column>
                        <h:outputText value="#{v2}"/>
                    </p:column>
                </p:dataTable>          
            </p:tab>
        </p:tabView>
    </h:form>

и внутри bean-компонента (просмотр в области видимости)

@ManagedBean
@ViewScoped
public class TstTab {

    private List<String> list1;
    private List<String> list2;

    public TstTab(){
        list1 = new ArrayList<String>();
        list2 = new ArrayList<String>();


        list1.add("List 1 - Str 1");
        list1.add("List 1 - Str 2");
        list1.add("List 1 - Str 3");
        list1.add("List 1 - Str 4");
        list1.add("List 1 - Str 5");

        list2.add("List 2 - Str 1");
        list2.add("List 2 - Str 2");
        list2.add("List 2 - Str 3");
        list2.add("List 2 - Str 4");
        list2.add("List 2 - Str 5");            
    }


    public void onDtlTabChanged(TabChangeEvent event) {
        System.out.println("000000000000000000");
    }


    public List<String> getList1() {
        System.out.println("11111111111111");
        return list1;
    }


    public List<String> getList2() {
        System.out.println("222222222222222222");
        return list2;
    }

}

теперь проблема заключается в том, что когда вы запускаете приложение и пытаетесь перемещаться (переключаться) между вкладками, но я вижу, что onDtlTabChanged вызывается после вызова геттеров, так что это большая проблема.

и если изменить tabView со статического на динамическое, то поведение будет случайным, другими словами вызов события изменения происходит где-то в середине геттеров.

Заранее спасибо.


person Ali Saleh    schedule 10.04.2013    source источник
comment
Вы установили dynamic = true, так почему вы обновили вкладку 1 в ajax?   -  person Rong Nguyen    schedule 10.04.2013
comment
У меня cache=false, поэтому, если пользователь перейдет на вторую вкладку, а затем перейдет на первую, мне придется снова получить данные   -  person Ali Saleh    schedule 11.04.2013
comment
Итак, если пользователь перейдет на вторую вкладку, а затем перейдет на третью вкладку?   -  person Rong Nguyen    schedule 11.04.2013
comment
Я не понял вашей точки зрения, идея состоит в том, что есть три вкладки, каждая из которых имеет таблицу данных, и мне нужно обновлять данные каждый раз, когда пользователь щелкает вкладку, но Primefaces загружает содержимое вкладки перед завершением события changeTab ajax   -  person Ali Saleh    schedule 11.04.2013
comment
Я тестировал с Primefaces 3.5 и jsf (morjarra 2.1.20), все работает нормально, поэтому сначала вы должны протестировать на простом примере и сослаться на приведенный выше код, удачи!   -  person Rong Nguyen    schedule 11.04.2013
comment
Спасибо, но я проверил это на очень простом примере, но он такой же (я обновил сообщение выше новым примером), чтобы сделать его более конкретным.   -  person Ali Saleh    schedule 11.04.2013


Ответы (3)


Ну, я думаю, что это ОШИБКА с простыми лицами, я нашел обходной путь, который выглядит следующим образом

  1. Не используйте глобальную форму (форма для самого tabView), вместо этого используйте форму для каждой вкладки (внутри нее, которая окружает данные)

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

Это все,

проблема заключалась в том, что запрос ajax находится внутри глобальной формы, и это приводит к тому, что таблицы данных сначала получают свои данные перед запросом ajax, странная вещь с Primefaces: если вы не добавите первую фиктивную вкладку, она всегда будет выполнять первую форму внутри вкладки и получить его данные, и это вызовет проблему

с уважением ,

person Ali Saleh    schedule 11.04.2013

Я думаю, что ответ Али Салеха правильный.

Если у вас возникли проблемы с tabchangelistener, возможно, это может вам помочь:

У меня была аналогичная проблема с Primefaces 5.1.

Пока я помещал вкладку в форму, все работало нормально. Но поскольку я хотел использовать отдельные формы на своих вкладках, мне пришлось удалить окружающую форму вкладки, чтобы избежать вложенных форм. Без окружающей формы событие ajax больше не срабатывало при смене вкладки.

Мое решение состояло в том, чтобы использовать удаленную команду в форме, параллельной представлению вкладок.
Удаленная команда запускается атрибутом onTabChange элемента tabview. При этом вызове я перенаправил параметр индекса в глобальные параметры запроса.

<p:tabView id="rootTabMenu" styleClass="tabcontainer" prependId="false" 
        activeIndex="#{sessionData.activeTabIndex}" widgetVar="rootTabMenu"
        onTabChange="tabChangeHelper([{name: 'activeIndex', value: index}])">
    // Tabs...  
</p:tabView>

<h:form id="tabChangeHelperForm">
    <p:remoteCommand name="tabChangeHelper" actionListener="#{sessionData.onTabChange()}" />
</h:form>    

В компоненте поддержки я снова поймал значение из карты параметров запроса и установил активный индекс.

public void onTabChange()
{   
    FacesContext context = FacesContext.getCurrentInstance();
    Map<String, String> paramMap = context.getExternalContext().getRequestParameterMap();
    String paramIndex = paramMap.get("activeIndex");
    setActiveTabIndex(Integer.valueOf(paramIndex));
    System.out.println("Active index changed to " + activeTabIndex);
}    

Надеюсь, что это может помочь вам

person maimArt    schedule 14.11.2014
comment
Пожалуйста, не просто ссылайтесь на ответ. Здесь разрешено показывать решение и ссылку на ответ. Таким образом, спрашивающий все еще знает, что делать, когда URL-адрес больше не действителен. - person Benjamin Diele; 14.11.2014

Он отлично работает в Primefaces 3.5 и mojarra 2.1.20, мой код: bean:

@ManagedBean(name = "tabview")
@ViewScoped    
public class TabView implements Serializable {

        private static final long serialVersionUID = 1L;
        private List<Car> l1;
        private List<Car> l2;
        private List<Car> l3;

        public TabView() {
            l1 = new ArrayList<Car>();
            l2 = new ArrayList<Car>();
            l3 = new ArrayList<Car>();

            Car c1 = new Car("c1", "a1");
            Car c2 = new Car("c21", "a21");
            Car c3 = new Car("c31", "a31");
            Car c4 = new Car("c41", "a41");
            Car c5 = new Car("c51", "a51");
            Car c6 = new Car("c61", "a61");
            Car c7 = new Car("c71", "a71");
            Car c8 = new Car("c81", "a81");
            Car c9 = new Car("c91", "a91");
            l1.add(c1);
            l1.add(c2);
            l1.add(c3);

            l2.add(c4);
            l2.add(c5);
            l2.add(c6);

            l3.add(c7);
            l3.add(c8);
            l3.add(c9);
        }

        public void hand(TabChangeEvent event) {
            Car c1 = new Car("c1", "a1");
            Car c2 = new Car("c1", "a1");
            Car c3 = new Car("c1", "a1");
            Car c4 = new Car("c1", "a1");
            Car c5 = new Car("c1", "a1");
            Car c6 = new Car("c1", "a1");
            Car c7 = new Car("c1", "a1");
            Car c8 = new Car("c1", "a1");
            Car c9 = new Car("c1", "a1");
            l1.add(c1);
            l1.add(c2);
            l1.add(c3);

            l2.add(c4);
            l2.add(c5);
            l2.add(c6);

            l3.add(c7);
            l3.add(c8);
            l3.add(c9);
        }

        public List<Car> getL1() {
            return l1;
        }

        public void setL1(List<Car> l1) {
            this.l1 = l1;
        }

        public List<Car> getL2() {
            return l2;
        }

        public void setL2(List<Car> l2) {
            this.l2 = l2;
        }

        public List<Car> getL3() {
            return l3;
        }

        public void setL3(List<Car> l3) {
            this.l3 = l3;
        }
    }

xhtml:

  <p:tabView id="mtrlDtlTabs" dynamic="true" cache="false">  
                    <p:ajax event="tabChange" update="t1 t2 t3" listener="#{tabview.hand}"/>
                    <p:tab id="t1" title="1">
                        <p:dataTable id="l1" value="#{tabview.l1}" var="l1">
                            <p:column headerText="l1">#{l1.manufacturer}</p:column>
                            <p:column headerText="l2">#{l1.model}</p:column>
                        </p:dataTable>
                    </p:tab>
                    <p:tab id="t2" title="2">
                        <p:dataTable id="l2" value="#{tabview.l2}" var="l2">
                            <p:column headerText="l2">#{l2.manufacturer}</p:column>
                            <p:column headerText="l22">#{l2.model}</p:column>
                        </p:dataTable>
                    </p:tab>
                    <p:tab id="t3" title="3">
                        <p:dataTable id="l3" value="#{tabview.l3}" var="l3">
                            <p:column headerText="l3">#{l3.manufacturer}</p:column>
                            <p:column headerText="l33">#{l3.model}</p:column>
                        </p:dataTable>
                    </p:tab>
                </p:tabView>
person Rong Nguyen    schedule 11.04.2013
comment
Попробуйте добавить оператор печати в геттеры, и вы увидите странную последовательность их вызова. - person Ali Saleh; 14.04.2013