JSF 2.0动态表单最佳实践

时间:2013-10-30 18:24:15

标签: jsf jsf-2 binding

更新:对于那些将此标记为重复关闭的人来说,假设的重复问题与我要求的完全不同。我的问题是直到渲染时我不知道问题集是什么,将会有多少问题或者问题类型所以我不能使用“可能重复”中描述的技术回答。

我们的JSF 2.x应用程序的一部分需要向用户呈现问题集,其中问题和问题类型在运行时才知道。例如,我们有类似的东西(为了清晰起见,省略了getters / setter):

public class QuestionSet {
    private List<Section> sections;
}

public class Section {
    private String sectionTitle;
    private List<Question> questions;
    private SectionStatus status; // e.g. UNANSWERED, CURRENTLY_ANSWERING,ANSWERED, COMPLETED
}

public class Question {
    private String questionText;
    private QuestionType questionType; // E.G TEXT, RADIO, LIST, CHECKBOX
    private List<String> options; // for RADIO/LIST/CHECKBOX types
    private List<String> answers;
}

我们需要将每个部分呈现在一个单独的div中,具体取决于它的状态(例如,UNANSWERED会显示一个只有标题的div,ANSWERED将显示带有节标题和绿色刻度标记的div,而CURRENTLY_ANSWERING将呈现一个div与节标题,然后每个问题与基于问题类型的适当输入控件。

问题在运行期间也是动态的 - 例如如果用户对单选按钮问题回答“是”,则可能会提示进一步的子问题。

我目前正在使用绑定,即

<h:panelGroup binding = "#{bean.panelGroup}" /> 

并且在bean的getPanelGroup内手工创建组件树,比如HtmlPanelGroup,HtmlOutputText,带有ValueExpressions的UIInput等,但是在阅读BalusC的一些答案时,这个问题很好,特别是这个问题:How does the 'binding' attribute work in JSF? When and how should it be used?我想知道如果有“更好”的方法?

我担心的一件事是,在RECREATE_VIEW期间调用getter是出于链接问题中解释的原因(在调用绑定中引用的方法之后),因此除非我采取措施,在RECREATE_VIEW阶段,只返回我在最后一个RENDER_RESPONSE阶段创建的组件,这引入了重新创建我刚刚创建的东西的不必要的费用。

在这种情况下,JSF调用我的setter来设置我刚刚在绑定属性的getter中给它的东西似乎也没有意义。 (我的bean是View范围,因为我需要使用ajax来实现用户需要的一些功能)

思考/意见(特别是来自有用的BalusC)非常感谢......

2 个答案:

答案 0 :(得分:1)

在这种情况下,我没有太多理由使用组件绑定。您可以在视图中决定要渲染的内容和方式。您可以<ui:fragment> / <c:if>有条件地根据问题类型呈现元素,<ui:repeat> / <c:forEach>来处理问题集等。

因此,如果我正确理解了工作流程,您的问题集将在例如post构造方法:

@PostConstruct
public void init() {
    questionSet = service.get();//get it somehow
}

然后你将有一组部分,这些部分中的每一部分都将包含问题或答案,并且有效性将通过AJAX进行检查。如果我理解你,那么你可以有以下观点:

<h:form id="q-set">
    <ui:repeat value="#{bean.questionSet.sections}" var="section">
        <div>#{section.title}</div>
        <div class="#{section.status eq 'UNANSWERED' ? 'section-unanswered' : ... }"/>
        <ui:fragment rendered="#{section.status eq 'ANSWERED' ?}"><div class="tick"/></ui:fragment> ...
        <ui:fragment rendered="#{section.status eq 'ANSWERED' ?}">
            <ui:repeat value="#{section.questions}" var="question">
                <div>#{question.title}</div>
                <ui:fragment rendered="#{question.type eq 'RADIO'}">
                    <h:selectOneRadio value="#{question.answers[0]}" validator="...">
                        <f:selectItems value="#{question.options}" var="opt" itemLabel="#{opt}" ... />
                        <f:ajax ...>
                    </h:selectOneRadio>
                </ui:fragment>
                ...
            </ui:repeat>
        </ui:fragment>
    </ui:repeat>
</h:form>

答案 1 :(得分:0)

您的视图中似乎有太多的逻辑/条件。

如何在Java端生成视图programmatically

对于棘手的部分,您可以使用JavaScript和JSON。