我正在尝试使用以下代码调试问题:
<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>
答案 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();
.....
}