3
respostas

Efeito inverso ao atualizar tabelaLivros via ajax

Quando eu informo :tabelaLivros no atributo render está ocorrendo o seguinte erro: HTTP Status 500 - <f:ajax> contains an unknown id ':tabelaLivros' - cannot locate it in the context of the component j_idt20. Quando eu informo somente tabelaLivros não acontece nenhum erro e o ajax é executado corretamente, estou na dúvida pois parece é ao contrário da explicação.

livro.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:head />
    <h:body>
        <h1>Novo Livro</h1>
        <h:form>
            <h:messages id="messages"/>
            <fieldset>
                <legend>Dados do Livro</legend>
                <h:panelGrid columns="2">
                    <h:outputLabel value="Titulo:" for="titulo" />
                    <h:inputText id="titulo" value="#{livroBean.livro.titulo}"
                        required="true" requiredMessage="Título Obrigatório">
                            <f:validateLength maximum="40" />
                            <f:ajax event="blur" render="messages"/>
                        </h:inputText>
                    <h:outputLabel value="ISBN:" for="isbn" />
                    <h:inputText id="isbn" value="#{livroBean.livro.isbn}" validator="#{livroBean.comecaComDigitoUm}"/>

                    <h:outputLabel value="Preço:" for="preco" />
                    <h:inputText id="preco" value="#{livroBean.livro.preco}" label="Preço">
                        <f:validateDoubleRange minimum="1.0" maximum="1000.0"/>
    <!--                     <f:convertNumber type="currency" pattern="R$ #0.00" currencySymbol="R$" locale="pt_BR" /> -->
                    </h:inputText>

                    <h:outputLabel value="Data de Lançamento:" for="dataLancamento" />
                    <h:inputText id="dataLancamento"
                        value="#{livroBean.livro.dataLancamento.time}">
                        <f:convertDateTime pattern="dd/MM/yyyy HH:mm" />
                    </h:inputText>

                </h:panelGrid>
            </fieldset>
            <fieldset>
                <legend>Dados do Autor</legend>
                <h:outputLabel value="Selecione Autor:" for="autor" />
                <h:selectOneMenu id="autor" value="#{livroBean.autorId}">
                    <f:selectItems value="#{livroBean.autores}" var="autor"
                        itemLabel="#{autor.nome}" itemValue="#{autor.id}" />
                </h:selectOneMenu>
                <h:commandButton value="Gravar Autor" actionListener="#{livroBean.gravarAutor}">
                    <f:ajax execute="autor" render="tabelaAutores"/>
                </h:commandButton>
                <h:dataTable value="#{livroBean.autoresDoLivro}" var="autor" id="tabelaAutores">
                    <h:column>
                        <h:outputText value="#{autor.nome}" />
                    </h:column>
                </h:dataTable>
            </fieldset>
            <h:commandButton value="Gravar" actionListener="#{livroBean.gravar}">
                <f:ajax execute="@form" render="@form tabelaLivros"/>
            </h:commandButton>

            <h:dataTable id="tabelaLivros" value="#{livroBean.livros}" var="livro">
              <h:column>
                <f:facet name="header">Título</f:facet>
                <h:outputText value="#{livro.titulo}" />
              </h:column>

              <h:column>
                <f:facet name="header">ISBN</f:facet>
                <h:outputText value="#{livro.isbn}"/>
              </h:column>

              <h:column>
                <f:facet name="header">Preço</f:facet>
                <h:outputText value="#{livro.preco}" />
              </h:column>

              <h:column>
                <f:facet name="header">Data</f:facet>
                <h:outputText value="#{livro.dataLancamento.time}" >
                    <f:convertDateTime pattern="dd/MM/yyyy HH:mm"/>
                </h:outputText>
              </h:column>
            </h:dataTable>

        </h:form>
    </h:body>

</html>

LivroBean.java

public class LivroBean {

    private Livro livro = new Livro();
    private Integer autorId;

    public void comecaComDigitoUm(FacesContext fc, UIComponent component, Object value) {

        String valor = value.toString();
        if (!valor.startsWith("1")) {
            throw new ValidatorException(new FacesMessage("Deveria começar com 1"));
        }
    }

    public void gravar() {
        System.out.println("Gravando livro " + this.livro.getTitulo());

        if (livro.getAutores().isEmpty()) {
            FacesContext.getCurrentInstance().addMessage("autor", new FacesMessage("Livro deve ter pelo menos um Autor"));
            return;
        }

        new DAO<Livro>(Livro.class).adiciona(this.livro);
        this.livro = new Livro();
    }

    public void gravarAutor() {
        Autor autor = new DAO<Autor>(Autor.class).buscaPorId(autorId);
        System.out.println("Autor a ser adicionado: " + autor.getNome());
        this.livro.adicionaAutor(autor);
    }

    public List<Autor> getAutores() {
        List<Autor> autores = new DAO<Autor>(Autor.class).listaTodos();
        System.out.println("Número de autores encontrados: " + autores.size(
3 respostas

Opa Paulo, que estranho! Vou dar uma olhada para ver se acho alguma coisa, mas deveria rolar os : mesmo.

Fala Paulo Henrique, tudo bem?

Isso acontece devido aos NamingContainers do JSF. Se um componente que vc quer referenciar no ajax esta dentro do mesmo NamingContainer do componente que usa o ajax, vc deve passar apenas o id.

<h:form id="form">
    <p:commandLink update="result"> <!-- OK! -->
    <h:panelGroup id="result" />
</h:form>

Se ele não está no mesmo NamingContainer, então vc precisa passar a referência absoluta do id. Uma referência absoluta começa com o caractere de separação do NamingContainer que por default é :.

<h:form id="form">
    <p:commandLink update="result"> <!-- FALHA! -->
</h:form>
<h:panelGroup id="result" />

<h:form id="form">
    <p:commandLink update=":result"> <!-- OK! -->
</h:form>
<h:panelGroup id="result" />

Agora se vc estiver usando forms diferentes, ou seja NamingContainers diferentes, vc precisa passar o id do form tb:

<h:form id="form">
    <p:commandLink update=":result"> <!-- FALHA! -->
</h:form>
<h:form id="otherform">
    <h:panelGroup id="result" />
</h:form>

<h:form id="form">
    <p:commandLink update=":otherform:result"> <!-- OK! -->
</h:form>
<h:form id="otherform">
    <h:panelGroup id="result" />
</h:form>

espero ter ajudado =)

Ajudou sim Samir Bravo. Obrigado.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software