如何在不同的浏览器选项卡中将Primefaces数据表与不同的数据重复使用?

时间:2019-01-04 17:09:29

标签: jsf primefaces datatable cdi

我的应用程序的url中有一个查询参数,用于使用数据表中的相同xhtml(所有动态内容)呈现不同的数据。

bean的作用域是会话作用域,数据表呈现所有数据,并具有许多打开不同对话框的输入元素。

如果我打开另一个发送不同查询参数的浏览器选项卡,则数据表将完美呈现,但是如果我返回第一个选项卡,则所有命令链接都不会调用操作,并且整个应用程序将开始非常不正常地运行。 / p>

根据我的研究,这是因为我更改了数据表中的数据,因此尝试使用动态ID,动态窗口小部件名称对其进行命名,但似乎无济于事。

<f:metadata>
  <f:viewParam name="param" value="#{moduleBean.param}"/>
  <f:viewAction action="#{moduleBean.setup}" />
</f:metadata>

<c:set var="module" value="#{moduleBean.param}" />

<p:dataTable id="#{module}-dataTable" value="#{moduleBean.model[module]}" var="data">

  <p:commandLink action="#{moduleBean.openModuleDetails}" update=":#{module}-searchDialog" oncomplete="PF('#{module}-searchWidget').show();">
    <f:param name="module" value="#{module}" />
    <f:param name="dataRow" value="#{data.dbKey}" />
  </p:commandLink>
</p:dataTable>


@Named
@javax.faces.view.ViewScoped
public class ModuleBean implements Serializable {

   private String param;

   public void setup() throws IOException {
      this.model.put(this.param, new LazyDataModel(this.param));
   }

    public Map<String, LazyDataModel> getModel() {
        return model;
    }
}

这将在每个选项卡中使用所有正确的id构建所有预期的html,但是JSF仍未在命令链接中处理动作。不用说,如果我只使用一个浏览器选项卡,那么一切都将正常运行。

有时,它会在链接中单击两次后开始工作,但是在浏览器选项卡之间来回移动最终总是会使其崩溃。

在命令链接中添加动作侦听器也无法解决该问题。

关于如何使JSF将相同的数据表视为同一页面上的不同实体但具有不同参数的任何建议?

1 个答案:

答案 0 :(得分:2)

在不了解底层bean的情况下-如果将moduleBean放在@SessionScoped中,这将是预期的行为。会话(和会话作用域的Bean)在浏览器选项卡之间共享。因此,您不能依赖两个不同选项卡中的基础值。

尝试将表数据的后备值更改为@RequestScoped/@ViewScoped

这是一个可行的完整解决方案,请注意,此解决方案使用PrimeFaces 6.2,Apache Commons和Lombok;

@Data
@Named
@ViewScoped
public class TableTestBackingBean implements Serializable {
    private int param;

    @Inject
    private PersonsBean personsBean;

    public void onClicked() {
        System.out.println("Clicked fine!");
    }

    public List<Person> getPersons() {
        return personsBean.getPersons()[param];
    }
}
@Data
@ApplicationScoped
public class PersonsBean {
    @Data
    @AllArgsConstructor
    public class Person {
        private String firstName;
        private String lastName;
        private int age;
    }

    private List<Person> persons[];

    @PostConstruct void init() {
        persons = new List[4];

        for (int j = 0; j < 4; j++) {
            persons[j] = new ArrayList<>();

            for (int i = 0; i < 30; i++) {
                final String firstName =
                    RandomStringUtils.randomAlphanumeric(10);
                final String lastName = 
                    RandomStringUtils.randomAlphanumeric(10);
                final int age = RandomUtils.nextInt(0, 120);

                persons[j].add(new Person(firstName, lastName, age));
            }
        }
    }   
 }
<?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" xmlns:f="http://java.sun.com/jsf/core">
    <f:metadata>
        <f:viewParam name="param" value="#{tableTestBackingBean.param}"/>
    </f:metadata>
    <h:head>
            <title>Test</title>
    </h:head>
    <h:body>
        <p:dataTable value="#{tableTestBackingBean.persons}" var="t">
            <p:column headerText="First Name"><h:outputText value="#{t.firstName}" /></p:column>
            <p:column headerText="Last Name"><h:outputText value="#{t.lastName}" /></p:column>
            <p:column headerText="Age"><h:outputText value="#{t.age}" /></p:column>
        </p:dataTable>
        <h:form>
            <p:commandButton action="#{tableTestBackingBean.onClicked}" value="Click Me!" />
        </h:form>
    </h:body>
</html>

这将应用程序范围的Bean用于表数据,使其保持完全静态。这可以顺利进行,并且表格根据param中传递的参数以不同的方式呈现数据。