2013-10-30 79 views
0

更新:对于那些将此标记为重复关闭的标记,所假定的重复问题与我所要求的无关。我的问题是我不知道,直到渲染时间什么问题集,会有多少问题或什么问题类型将是,所以我不能使用“可能的重复”答案中描述的技术。JSF 2.0动态表单最佳实践

我们的JSF 2.x应用程序的一部分需要将问题集呈现给用户,问题和问题类型直到运行时才知道。例如,我们有这样的事情(为清楚起见省略getter/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每个部分,这取决于它的状态(例如未回答将显示一个div只是标题,就问会显示带有部分标题和绿色刻度标记的div,CURRENTLY_ANSWERING将使用部分标题呈现div,然后使用基于问题类型的适当输入控件显示每个问题。

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

我目前做这个用结合,即

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

和bean的getPanelGroup内的ValueExpressions等,它们工作正常,但在阅读一些BalusC的的手工创建全光照的事情组件树像HtmlPanelGroup,HtmlOutputText,UIInput回答,特别是对这个问题: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是视图范围内,我将需要使用AJAX对于一些我们的用户需要的功能)

思想/意见(尤其是从以往任何时候都很有帮助BalusC)不胜感激...

+0

[JSF:动态更改窗体]的可能重复(http://stackoverflow.com/questions/5654269/jsf-dynamically-change-form) – 757071

+0

有关如何绑定工作检查的详细信息:http://stackoverflow.com/questions/14911158/how-binding-attribute-in-jsf-works – 757071

+0

@johny,我不希望听起来那么尖锐,但你还没有正确地阅读我的问题。这是最肯定不是你的评论中的第一个链接的重复 - 正如我所说,我不知道,直到我查询数据库有多少问题会有什么问题类型将是,所以我不能在你的wy中使用ajax “可能的欺骗”问题。此外,我在我的文本中链接到相同的绑定文章!事实上,这是什么促使我的问题。 –

回答

1

我不看到在这种情况下使用组件绑定的很多理由。您可以在视图中决定要渲染什么以及如何渲染。你可以有<ui:fragment>/<c:if>有条件地呈现基础上问题类型的元素,<ui:repeat>/<c:forEach>来处理问题集等

所以,如果我理解正确的工作流程,你的问题集将在例如确定后期构造方法:

@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> 
+0

不!再一次,我不知道问题的类型会是什么!所以在你的情况下,你已经显示了一个selectOneRadio,但它可能是一个h:inpuText或一个h:selectBooleanCheckbox或一个h:selectOneMenu等等,并且这个集合中的每个问题都可能是不同的类型。例如,我可以得到“你喜欢猫吗?”单选按钮问题,然后是“你的猫是什么颜色?”需要一个下拉列表,然后是一个“请评论”,这需要一个输入文本框。或者我可以得到“你最喜欢的3个饼干是什么?”和一个cookie选项的复选框列表,然后“你多大了?”下拉列表等。 –

+1

您是否在内部迭代组件中看到省略号?您需要在其中放置另一个片段,以便涵盖每个问题类型,并因此根据问题类型呈现每个HTML DOM元素。例如。 ''' ui:fragment rendered =“#{question.type eq'DROPDOWN'}”>'等 – skuntsel

0

它看起来像你将有太多的逻辑/条件在您的视图。

如何在Java端生成视图programmatically

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

+0

这就是我现在正在做,我正在询问关于是否有“更好”的方式的意见:) –

+0

我必须承认我不是JSF的高度动态形式的粉丝......在某些情况下,我只是使用JavaScript/JSON而不是纯粹的JSF/Facelets解决方案。 –