Como inserir um objeto em uma view JSF 2.3

Amigos, preciso de ajuda com um problema.

Conforme o código abaixo, preciso que um determinado objeto seja instanciado em uma view de acordo com o que eu escolher em um SelectOneMenu. Pesquisei algumas coisas a respeito, mas não consegui, talvez por pouco conhecimento, encontrar a resposta.

    @Named
@ViewScoped
public class UnidadeBean implements Serializable {

	private static final long serialVersionUID = 1L;

	
	private Unidade unidade;

	@Inject
	private Bloco bloco;
	
	@Inject
	private UnidadeService unidadeService;

	private List<Unidade> listaUnidades;

	private List<Bloco> listaBlocos;

	private Bloco blocoSelecionado;

	// Construtor reinicializando valores do formulario
	
	

	// Metodo reinicialiaza objetos e valores
	public void limparFormulario() {

		unidade = new Unidade();

	}
	
	public void novaUnidade() {
		
		unidade = new Unidade();
	}

	public void setBloco(Bloco bloco) {
		this.bloco = bloco;
	}

	public void adicionarUnd() {

		bloco.getUnidades().add(unidade);
		unidade.setBloco(bloco);

	}

	public Unidade salvarUnidade() {

		unidadeService.salvarUnidade(unidade);
		MessagesFaces.addInfoMessage("Unidade salva com sucesso");
		limparFormulario();

		return null;
	}

	public Bloco salvarBloco() {

		unidadeService.salvarBloco(bloco);

		MessagesFaces.addInfoMessage("Bloco salvo com sucesso, acrescente unidades");

		return null;
	}

	public void listarBlocos() {

		if (FacesUtil.isNotPostback()) {
			this.listaBlocos = unidadeService.listarBloco();
		}

	}

	public List<Unidade> getListaUnidades() {

		this.listaUnidades = unidadeService.listarUnidade();
		return this.listaUnidades;
	}

	public Unidade getUnidade() {
		return unidade;
	}

	public void setListaBlocos(List<Bloco> listaBlocos) {
		this.listaBlocos = listaBlocos;
	}

	public List<Bloco> getListaBlocos() {
		return listaBlocos;
	}

	public Bloco getBlocoSelecionado() {
		return blocoSelecionado;
	}

	public void setBlocoSelecionado(Bloco blocoSelecionado) {
		this.blocoSelecionado = blocoSelecionado;
	}

	public Bloco getBloco() {
		return bloco;
	}

}

View

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://xmlns.jcp.org/jsf/html"
	xmlns:f="http://xmlns.jcp.org/jsf/core"
	xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
	xmlns:p="http://primefaces.org/ui"
	template="WEB-INF/templates/Layout.xhtml">

	<ui:define name="content">

		<f:metadata>
			<f:event listener="#{unidadeBean.listarBlocos}" type="preRenderView"></f:event>
		</f:metadata>


		<div class="ui-fluid">
			<h1 class="aw-page-title">Cadastro das Unidades do condomínio</h1>

			<h:form id="form">

				<p:messages autoUpdate="false" closable="true" />

					<p:panelGrid id="grid1" columns="2" layout="grid"
						style="margin-bottom: 15px" styleClass="panelgrid-noborder"
						columnClasses="ui-grid-col-6, ui-grid-col-6">

						<p:outputLabel value="Unidade: " for="unidade" />
						<p:inputText id="unidade" label="Unidade"
							value="#{unidadeBean.unidade.unidade}" />

						<p:outputLabel value="Numero de Moradores: " for="nMoradores" />
						<p:spinner id="nMoradores"
							value="#{unidadeBean.unidade.qtdeMorador}" min="0" max="10">
							<f:convertNumber />
						</p:spinner>

						<p:outputLabel value="Bloco: " for="bloco" />
						<p:selectOneMenu id="bloco" value="#{unidadeBean.bloco}">
							<f:converter binding="#{blocoConverterNamed}" />
							<f:selectItem itemLabel="Selecione o seu bloco" />
							<f:selectItems value="#{unidadeBean.listaBlocos}" var="bloco"
								itemValue="#{bloco}" itemLabel="#{bloco.bloco}" />
						</p:selectOneMenu>

						<p:outputLabel />

						<p:commandButton value="Adicionar Apto"
							action="#{unidadeBean.adicionarUnd}" process="grid1"
							update="tableUnidades grid1" />

					</p:panelGrid>

				<p:toolbar style="margin-bottom: 15px">

					<p:toolbarGroup>
						<p:commandButton value="Salvar"
							action="#{unidadeBean.salvarUnidade}" process="@this tableUnidades"
							update="@form" />
					</p:toolbarGroup>

				</p:toolbar>

				<p:separator style="margin-top: 10px" />

				<p:dataTable id="tableUnidades"
					value="#{unidadeBean.bloco.unidades}" var="unidade" reflow="true"
					emptyMessage="Não existem unidades cadastradas">
					<p:column headerText="Unidade">
						<h:outputText value="#{unidade.unidade}" />
					</p:column>
					<p:column headerText="Qtde. Moradores">
						<h:outputText value="#{unidade.qtdeMorador}">
							<f:convertNumber />
						</h:outputText>
					</p:column>
					<p:column headerText="Bloco">
						<h:outputText value="#{unidade.bloco}" converter="blocoConverter" />
					</p:column>

				</p:dataTable>
			</h:form>

		</div>

	</ui:define>

</ui:composition>

Vamos a resolução:

** Partindo do seu selectOneMenu

<p:outputLabel value="Bloco: " for="bloco" />
						<p:selectOneMenu id="bloco" value="#{unidadeBean.bloco}">
							<f:converter binding="#{blocoConverterNamed}" />
							<f:selectItem itemLabel="Selecione o seu bloco" />
							<f:selectItems value="#{unidadeBean.listaBlocos}" var="bloco"
								itemValue="#{bloco}" itemLabel="#{bloco.bloco}" />
						</p:selectOneMenu>

1 - No seu manageBean crie uma variavel tipo boolean, por exemplo com a seguinte descrição: mostrarLabelSeOBlocoForCodigo1.

private boolean mostrarLabelSeOBlocoForCodigo1 = false;

2 - Criar o métodos de acesso, porém no metodo is, colocar um IF que vai fazer a checagem do status, digamos:

public boolean isMostrarLabelSeOStatusForCodigo1() {
this.mostrarLabelSeOStatusForCodigo1 = false;

		if (this.getBloco().getCodigo() == 1) {
			this.mostrarLabelSeOStatusForCodigo1 = true;
		}


	return mostrarLabelSeOStatusForCodigo1;
}

3 - Na view criar um objeto qualquer, exemplo um label e setar a propriedade rendered para a nossa mais nova variável.

<p:outputLabel
						value="Exibir label em caso do bloco ser igual a 1"
						rendered="#{unidadeBean.mostrarLabelSeOStatusForCodigo1}"  />

4 - Inserir um evento ajax toda vez que atualizar o selectOneMenu, também seja atualizado o formulario de modo a exibir ou não o label.

<p:selectOneMenu id="bloco" value="#{unidadeBean.bloco}">
							<f:converter binding="#{blocoConverterNamed}" />
							<f:selectItem itemLabel="Selecione o seu bloco" />
							<f:selectItems value="#{unidadeBean.listaBlocos}" var="bloco"
								itemValue="#{bloco}" itemLabel="#{bloco.bloco}" />

<p:ajax event="change" process="@this" update="form"></p:ajax>
						</p:selectOneMenu>

Ola Andre, antes de mais nada, obrigado por sua resposta!

Conforme conversamos por whats, segue o Conversor do objeto bloco, e aproveito para enviar o model dele.

Objeto bloco:

        package br.com.mrzappa.c_project.model;

        import java.io.Serializable;
        import java.util.ArrayList;
        import java.util.List;

        import javax.persistence.CascadeType;
        import javax.persistence.Entity;
        import javax.persistence.FetchType;
        import javax.persistence.GeneratedValue;
        import javax.persistence.GenerationType;
        import javax.persistence.Id;
        import javax.persistence.ManyToOne;
        import javax.persistence.OneToMany;
        import javax.persistence.Table;

        import org.hibernate.validator.constraints.NotBlank;

        @Entity
        @Table(name = "bloco")
        public class Bloco implements Serializable {

        	private static final long serialVersionUID = 1L;

        	@Id
        	@GeneratedValue(strategy = GenerationType.IDENTITY)
        	private Long id;

        	@NotBlank
        	private String bloco;

        	@ManyToOne
        	private Condominio condominio;

        	@OneToMany(mappedBy = "bloco", cascade = CascadeType.ALL, fetch=FetchType.EAGER)
        	private List<Unidade> unidades = new ArrayList<>();

        	public String getBloco() {
        		return bloco;
        	}

        	public void setBloco(String bloco) {
        		this.bloco = bloco;
        	}

        	public Condominio getCondominio() {
        		return condominio;
        	}

        	public void setCondominio(Condominio condominio) {
        		this.condominio = condominio;
        	}

        	public List<Unidade> getUnidades() {
        		return unidades;
        	}

        	public void setUnidades(List<Unidade> unidades) {
        		this.unidades = unidades;
        	}

        	public Long getId() {
        		return id;
        	}

        	@Override
        	public int hashCode() {
        		final int prime = 31;
        		int result = 1;
        		result = prime * result + ((id == null) ? 0 : id.hashCode());
        		return result;
        	}

        	@Override
        	public boolean equals(Object obj) {
        		if (this == obj)
        			return true;
        		if (obj == null)
        			return false;
        		if (getClass() != obj.getClass())
        			return false;
        		Bloco other = (Bloco) obj;
        		if (id == null) {
        			if (other.id != null)
        				return false;
        		} else if (!id.equals(other.id))
        			return false;
        		return true;
        	}

        	
        	 @Override
        	 public String toString() { return String.format("%s[id=%d]",
        	 getClass().getSimpleName(), getId()); }
        	

        }

    BlocoConverter:

    package br.com.mrzappa.c_project.util.converters;

    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    import javax.faces.convert.Converter;
    import javax.faces.convert.ConverterException;
    import javax.faces.convert.FacesConverter;
    import javax.inject.Inject;

    import br.com.mrzappa.c_project.model.Bloco;
    import br.com.mrzappa.c_project.model.service.UnidadeService;

     
    @FacesConverter(value = "blocoConverter", managed = true)
    public class BlocoConverter implements Converter<Bloco>{
    	
    	@Inject
    	private UnidadeService unidadeService;

    	@Override
    	public Bloco getAsObject(FacesContext context, UIComponent component, String value) {
    		if (value == null || value.isEmpty()) {

    			return null;
    		}

    		if (!value.matches("\\d+")) {
    			throw new ConverterException("O value não é um numero valido: " + value);
    		}

    		Long id = Long.parseLong(value);
    		return unidadeService.buscarBloco(id);
    	}

    	@Override
    	public String getAsString(FacesContext context, UIComponent component, Bloco value) {
    		if (value == null) {
    			return null; // Ou uma string vazia.
    		}
    		if (!(value instanceof Bloco)) {
    			throw new ConverterException("O valor não é um tipo Uninade : " + value);
    		}

    		Long id = ((Bloco) value).getId();
    		return (id != null) ? String.valueOf(id) : null;
    	
    	}

    }

No ManagedBean criei um métdo boolean:

[CODE]
public boolean seuMetodo() {
if(this.seuBean.getSeuAtributo().equalsIgnoreCase(“SIM”)){

           // faça alguma coisa
    }else {  
    	faça outra  
    }  
    return isRenderiza;
}

[/CODE]

Na pagina:

[CODE]
<h:outputText value="Fiz uma pergunta " />
<p:selectOneMenu

	value="#{managedBean.bean.atributo}">			
	
	<f:selectItem itemLabel="" itemValue="" />													
	<f:selectItem itemLabel="SIM" itemValue="SIM"/>
	<f:selectItem itemLabel="NÃO" itemValue="NAO" />
	<f:selectItem itemLabel="NÃO SEI" itemValue="NÃO SEI" />
					
	<p:ajax														 
		  event="change"														  														  														 
		  listener="#{managedBean.seuMetodo}" />																					
</p:selectOneMenu>

[/CODE]

Obrigado pela resposta, mas não é bem isto amigo !

Eu preciso ATRIBUIR o objeto selecionado no SELECTONEMENU na VIEW, para que ele possa ser editado.

O objeto precisa estar ativo na view. Eu tenho aqui uma receita de bolo para fazer isto usando VIEWPARAM, passando o id do objeto de uma outra página, mas o que eu quero fazer é na mesma página usando um seletor qualquer.

O código abaixo utiliza ajax para executar um método quando a opção selecionada do menu muda de valor e atribui a opção selecionada a um atributo do bean (O bean não pode ser RequestScoped, pois o ajax dispara uma requisição e o bean morrerá) e então atualiza o painel de edição

  <p:selectOneMenu value="#{bean.produto}" converter="produtoConverter">
    <p:ajax event="change" listener="#{bean.metodo}"  process="@this" update="painelEdicao"/>
    
    <f:selectItems value="#{bean.listaProdutos}" var="p" itemLabel="#{p.nome}" itemValue="#{p}"/>
  </p:selectOneMenu>

    <p:outputPanel id="painelEdicao" rendered="#{not empty bean.produto}">
     //codigo qualquer
    </p:outputPanel>

PS:Fiz o código aqui no guj mesmo

1 curtida

Obrigado pela resposta Mike.

Neste seu código, o que seria o bean.metodo ?

Seria um método qualquer do seu bean, se você quiser printar no console toda vez que selecionar uma opcao do selectOneMenu, basta criar um método e referencia-lo no listener do p:ajax

1 curtida

Mike, dentro da lógica do seu código, vou tentar te explicar a minha necessidade. Como eu sou um completo “noob”, de repente posso estar me atrapalhando e atrapalhando vocês.

Ao fazer uma seleção no selectOneMenu, eu quero ter uma instancia referente ao objeto selecionado. Por exemplo, seleciono “Notebook modelo 1000”, após a seleção, preciso ter este PRODUTO disponível e ativo na view, para que eu possa , por exemplo, acrescentar alguma “List”, não existente ainda, e desta forma, após incluir as “característicasTecnicas”, que seriam relacionadas via dataTable, eu salvaria.

Se eu fizesse isto vindo de outra página, seria assim:

Na VIEW que estivesse enviando o objeto, eu teria um button, que faria o envio do objeto "

<p:button … outcome="./edicaoProduto" /> <f:param name=“produto” value="#{produto.id}

Na VIEW que estivesse recebendo (edicaoProduto) teriamos algo como

<f:metadata> <f:viewparam name=“produto” value="#{edicaoProdutoBean.produto}"

Ó codigo que eu postei faz exatamente isso…
É só você adaptar ele

1 curtida

O seu selectOneMenu esta atribuindo o valor pra unidade.bloco

Você quer mostrar que atributo em que lugar? Se me falar, fica mais fácil de te ajudar

Esta gerando algum erro?

Mike, a sua lógica esta bem clara, a confusão realmente é minha.

Eu preciso construir um método, no listener do seu código, que atribua o valor selecionado no SelectOneMenu, para a view. Eu já consegui fazer algumas coisas funcionarem, mas sinto que foi na base da “gambiarra”. Esta view em questão faz o cadastro de apartamentos a um determinado bloco já cadastrado. O selectOne Menu é para “ativar” o bloco na view , ai tenho o DIALOG, que atribui os apartamentos a este bloco, e depois salva.

Em uma tela simples, sem usar o datatable, cadastrando 1 a 1, eu consigo salvar as unidades sem problemas. Mas estou encontrando dificuldade de atribuir o datatable (array de unidade) para o bloco.

Esta tela tem que ficar de tal forma que, bastando eu selecionar o objeto no SelectOneMenu, ela já preencha os campos da view, referentes ao objeto selecionado, neste caso BLOCO e, desta forma, poderei alterar e acrescentar coisas a este objeto ativo.

Cara, se foi confuso, eu deleto este post e tento explicar de outra forma. Não tem frescura comigo, sei que sou bem cru ainda na coisa. :wink:

Então, você não atribui a opção do selectOneMenu a view, você atribui ao seu bean, e na view vc referencia o seu atributo

O atributo value do selectOneMenu que atribui a opção selecionada ao seu atributo do seu bean

O listener serve para executar um método qualquer, se você quiser apenas atribuir a opção selecionada ao seu atributo, você pode remover o listener

Você quer inserir os atributos da opção selecionada na datatable ou em que?

1 curtida

Mike, você fala bem qualquer idioma, fora o português? O que estava acontecendo foi uma conversa entre alguém que fala uma lingua e outro que só sabe dizer bom dia e boa tarde, eu no caso. :joy:

Sua dica e, sua paciência, foram de muita ajuda e com a seguinte adaptação do seu codigo, o problema foi resolvido:

<p:selectOneMenu id=“bloco” value="#{unidadeBean.bloco}" >
<f:converter binding="#{blocoConverterNamed}" />
<p:ajax event=“change"
process=”@this" update=“panelBloco” />
<f:selectItem itemLabel=“Selecione o seu bloco” itemValue="" />
<f:selectItems value="#{unidadeBean.listaBlocos}" var=“bloco"
itemValue=”#{bloco}" itemLabel="#{bloco.bloco}" />
</p:selectOneMenu>

Como a vida não é perfeita, com a resolução desta lógica, surgiu outra bucha, mas para resolvê-la irei pesquisar antes ou, se for o caso, abrirei outro post, pois este foi resolvido!

Muito obrigadopor tudo grande Mike !

Haha que isso :+1:
Qualquer coisa só postar, se eu puder ajudar, eu irei ajudar :+1:

Mas que bom que deu certo!
Abraço

1 curtida