Динамически отображаемое содержимое JSF 2 в области запроса - слушатель не вызывается при работе с динамическим содержимым - PullRequest
1 голос
/ 16 января 2012

Я изложил свой проблемный случай ниже, что упрощает мою реальную проблему.Изменяя Bean на @SessionScoped, я могу решить эту проблему, но это действительно нежелательно.Как и @ViewScoped.Я думаю, что это должно работать в @RequestScoped.Мои вопросы:

  • Почему JSF нужен доступ к #{simpleBean.outerStrings} для вызова #{simpleBean.processInnerClick()} прослушивателя (externalStrings умрет в предыдущем запросе)
  • Какой шаблон лучшедля решения этой проблемы?

Рад отредактировать, чтобы прояснить ситуацию - просто дайте мне знать.

Класс бинов

import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class SimpleBean implements Serializable {

    private List<String> topLevelStrings = 
               Arrays.asList("TopLevel1", "TopLevel2");

    private List<String> outerStrings;

    private List<String> innerStrings;

    public void processOuterClick() {
        System.err.println("processOuterClick()");
        outerStrings = Arrays.asList("Outer1", "Outer2", "Outer3");
    }

    public void processInnerClick() {
        System.err.println("processInnerClick()");
        innerStrings = Arrays.asList("InnerA", "InnerB", "InnerC");
    }

    public List<String> getOuterStrings() {
        return outerStrings;
    }

    public List<String> getInnerStrings() {
        return innerStrings;
    }

    public List<String> getTopLevelStrings() {
        return topLevelStrings;
    }

}

XHTML

<h:form>
<ui:repeat var="toplevel" value="#{simpleBean.topLevelStrings}"
           id="toplevel_id">
<h:commandLink id="toplevel_command">
#{toplevel} <br/>
<f:ajax render="outerlevel_panel" 
        listener="#{simpleBean.processOuterClick()}"/>
</h:commandLink>
<h:panelGroup id="outerlevel_panel">
<ui:repeat var="outerLevel" value="#{simpleBean.outerStrings}" 
    id="outerlevel_id">
<h:commandLink id="outerlevel_command">
#{outerLevel} <br/> 
<f:ajax listener="#{simpleBean.processInnerClick()}" render="innerlevel_panel"/>                   
</h:commandLink>                            
<h:panelGroup id="innerlevel_panel">
<ui:repeat var="innerLevel" value="#{simpleBean.innerStrings}" 
           id="innerlevel_id">
<h:commandLink id="innerlevel_command">
#{innerLevel} <br/>        
</h:commandLink>
</ui:repeat>
</h:panelGroup>
</ui:repeat>
</h:panelGroup>         
</ui:repeat>
</h:form>

В основном:

  • Слушатель #{simpleBean.processOuterClick()} срабатывает нормально, а ссылки на команды # {outerLevel} отображаются
  • Но когда янажмите на команду #{outerLevel} Ссылка #{simpleBean.processInnerClick()} слушатель никогда не запускается

1 Ответ

2 голосов
/ 16 января 2012

Область запроса - неправильная область для этого конкретного требования.Bean-объект bean-объекта ограничивается концом ответа, и в последующем запросе будет создан новый объект со всеми его свойствами, установленными по умолчанию.В терминах JSF2 вам действительно нужна область просмотра.Область действия сеанса действительно слишком широка и намного хуже для этого требования, чем область запроса (когда конечный пользователь открывает одну и ту же страницу в нескольких окнах / вкладках, они физически совместно используют один и тот же компонент, что приводит к неинтуитивному поведению для каждого просмотра, когдаEnduser переключается между представлениями после взаимодействия).

Все, что вам нужно сделать, чтобы решить вашу конкретную проблему, это использовать @ManagedBean @ViewScoped:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class SimpleBean implements Serializable {
    // ...
}

Поскольку по какой-то причине вы предпочитаете управление CDI, а не JSF, альтернативой @ViewScoped для CDI является @ConversationScoped.

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;

@Named
@ConversationScoped
public class SimpleBean implements Serializable {

    @Inject
    private Conversation conversation;

    @PostConstruct
    public void init() {
        conversation.begin();
    }

    public String navigateToOtherPage() {
        conversation.end();
        return "otherPage?faces-redirect=true";
    }

    // ...
}

Вам нужно толькоуправлять началом и концом разговора самостоятельно .

См. также:

...