пустой интерфейс: повторить, компонент создан? - PullRequest
1 голос
/ 28 сентября 2011

Я пытаюсь отладить проблему с помощью следующего кода:

<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);
        }
    }
}

Дао просто выбирает элементы из базы данных.Вот соответствующий код загрузки файла:

<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 Ответ

1 голос
/ 28 сентября 2011

Хорошо, разместите его здесь, потому что он будет длиннее, чем комментарии.

Это работает для меня, что, вероятно, не то, что вы хотели услышать :( но мне пришлось сказать несколько мелких вещей. Во-первых, в контроллер добавить

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.

Вы не можете избежать двух вызовов вашего get, которые являются частью JSF lifeCycle и являются нормальными.
Как бы то ни было, вы можете избегать двойного попадания в базу данных, как и следовало бы, но рефакторинг вашего кода должен выглядеть так:

 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();

        .....
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...