空ui:重复,是否创建了组件?

时间:2011-09-28 03:16:23

标签: forms jsf-2

我正在尝试使用以下代码调试问题:

<h:panelGroup id="items">
<ui:repeat value="#{itemController.items}" var="item">
    <h:form>
        <h:inputText id="title" value="#{item.fields['Title']}"/>
        <a4j:commandButton action="#{dao.storeItem(item)}" value="Save" render="@form"/>
    </h:form>
</ui:repeat>
</h:panelGroup>

如果直接在视图中显示集合,则上述方法有效。但是,如果ui:repeat开始为空,并且通过AJAX请求添加了项目,并且ui:repeat重新呈现,则表单会中断。具体而言,模型不会更新,也不会触发操作。我想了解原因。

现在我的猜测是,如果ui:repeat开始为空,则根本不会创建表单组件。任何人都可以验证这一点,或提供正确的解释吗?

附加信息

以下是控制器的相关部分,我也尝试过ViewScoped和长时间运行的对话:

@Named
@ConversationScoped
public class ItemController implements Serializable
{   
    private static final long serialVersionUID = 1L;

    @Inject
    private HibernateDAO dao;    

    public List<Item> getItems()
    {
        return dao.getItems();
    }

    public void uploadListener(final FileUploadEvent event)
    {
        final UploadedFile item = event.getUploadedFile();

        final FacesContext context = FacesContext.getCurrentInstance();
        final Application application = context.getApplication();
        final String messageBundleName = application.getMessageBundle();
        final Locale locale = context.getViewRoot().getLocale();
        final ResourceBundle resourceBundle = ResourceBundle.getBundle(messageBundleName, locale);

        final String msg = resourceBundle.getString("upload.failed");
        final String detailMsgPattern = resourceBundle.getString("upload.failed_detail");

        try
        {
            CSVImporter.doImport(item.getInputStream(), dao, item.getName());
        }
        catch (ParseException e)
        {
            final Object[] params = {item.getName(), e.getMessage()};
            final String detailMsg = MessageFormat.format(detailMsgPattern, params);
            final FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, detailMsg);

            context.addMessage("uploadForm:uploader", facesMsg);
        }
        catch (TokenMgrError e)
        {
            final Object[] params = {item.getName(), e.getMessage()};
            final String detailMsg = MessageFormat.format(detailMsgPattern, params);
            final FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, detailMsg);

            context.addMessage("uploadForm:uploader", facesMsg);
        }
    }
}

dao simple从数据库中提取项目。以下是相关的文件上载代码:

<h:form id="uploadForm" enctype="multipart/form-data">          
    <h:message id="message" showDetail="true" for="uploader" errorClass="error" warnClass="warning" infoClass="info" fatalClass="fatal"/>
    <rich:fileUpload id="uploader"
        fileUploadListener="#{itemController.uploadListener}"
        maxFilesQuantity="1"
        acceptedTypes="csv"
        render="items message" />            
</h:form>

1 个答案:

答案 0 :(得分:1)

好在这里发帖,因为它会比评论更长。

它适用于我,这可能不是你想听到的:(但我不得不琐碎一些小事。首先在控制器添加

public void storeItems(Item item)
{
  dao.storeItems();
}

然后改变这个

 <a4j:commandButton action="#{dao.storeItem(item)}" value="Save" render="@form"/>

<a4j:commandButton action="#{itemController.storeItem(item)}" value="Save" render="@form"/>

然而,这可能不是真正的问题,我认为这是在这里

CSVImporter.doImport(item.getInputStream(), dao, item.getName());

基本上我希望上面的方法可以上传dao.getItems();可以获取它的数据。因此,在public List<Item> getItems()处放置一个断点,一旦文件上传,render="items message"再次呈现项目面板组,它应该会触及此方法,并在那时查看dao.storeItems()是否带回任何数据它应该。回复然后我们将从那里接受。


更新以下内容以避免两次运行dao fetch。

你无法避免两次调用你的JSF生命周期的部分并且是正常的 你怎么能避免两次击中数据库,但是按照

的方式重构你的代码
 private List<Item> items;

    public List<Item> getItems()
    {
        return items;
    }

    @PostConstruct
    public void init()
    {
        this.items = dao.getItems();
    }


    public void uploadListener(FileUploadEvent  event) throws Exception{
        ......
        CSVImporter.doImport(item.getInputStream(), dao, item.getName());
        this.items = dao.getItems();

        .....
    }