Edit with Radio button in jsf

Asked

Viewed 558 times

0

Well I’m starting now to develop with JSF and I’m with a doubt of how to do for my method edit receive the right object of the radio button , the way it is implemented it always takes the first of the table and not what is selected by the radio, what I missed ?

JSF

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
    <link rel="stylesheet" href="#{resource['css:materialize.min.css']}" type="text/css"/>
    <link rel="stylesheet" href="#{resource['css:style.css']}" type="text/css"/>
    <title>Usuários</title>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>

</h:head>
<style>
    .fixed-action-btn.horizontal ul {
        top: 47%;
    }

</style>
<h:body>
    <script type="text/javascript" src="#{resource['js:jquery-3.2.1.min.js']}"/>
    <script type="text/javascript" src="#{resource['js:materialize.min.js']}"/>
    <script type="text/javascript" src="#{resource['js:scripts.js']}"/>
    <nav>
        <div class="nav-wrapper indigo lighten-1">
            <h:graphicImage value="#{resource['imagens:logo_white.png']}" class="brand-logo center"/>
            <ul id="nav-mobile" class="left">
                <li>  <a id="menu" href="#">
                        <i class="material-icons">menu</i>
                    </a>   
                </li>
            </ul>
            <ul id="nav-mobile" class="right hide-on-small-only">


                <li>  <a id="menu" href="#">Settings</a>   
                </li>
            </ul>

        </div>
    </nav>


    <h:messages />
    <div class="divDados  grey lighten-4">

        <div class="divCima indigo lighten-2">

            <div class="fixed-action-btn horizontal click-to-toggle right ">
                <a class="btn-floating  indigo lighten-1 z-depth-3">
                    <i class="material-icons">menu</i>
                </a>
                <ul>
                    <li><a class="btn-floating purple darken-4 z-depth-3"  href="../index.jsf"><i class="material-icons">home</i></a></li>
                    <li><a class="btn-floating red darken-1 z-depth-3"><i class="material-icons">delete</i></a></li>
                    <li><h:form>
                            <h:commandLink id="menu" styleClass="btn-floating yellow darken-1 z-depth-3" action="#{BeanUsers.editar()}">
                                <i class="material-icons">mode_edit</i>
                                <f:setPropertyActionListener target="#{BeanUsers.selectedItem}"
                                                             value="#{usuario}" />
                            </h:commandLink>
                        </h:form></li>
                    <li><h:form>
                            <h:commandLink id="menu" styleClass="btn-floating green darken-1 z-depth-3" action="#{BeanUsers.cadastrar}">
                                <i class="material-icons">add</i>
                            </h:commandLink>
                        </h:form></li>
                </ul>
            </div>
            <h4 class="white-text" style="text-align: center">Usuários</h4>
        </div>
        <div class=" dadosListar container"> 

            <h:form>

                <h:dataTable binding="#{BeanUsers.dataTable}" value="#{BeanUsers.listar()}" var="usuario" rules="row" cellpadding="5" styleClass="bordered striped" >
                    <f:facet name="header">Selecionar</f:facet>

                    <h:column>
                        <h:selectOneRadio value="#{BeanUsers.usuario}"  valueChangeListener="#{BeanUsers.setSelectedItem}" onclick="selectOneRadio(this)">
                            <f:selectItem    itemValue="#{usuario}"  />
                        </h:selectOneRadio>
                    </h:column>
                    <h:column>

                    </h:column>
                    <h:column>
                        <f:facet name="header">Ativo</f:facet>
                            #{usuario.ativo}

                    </h:column> 
                    <h:column>
                        <f:facet name="header">Nome</f:facet>
                            #{usuario.nome}
                    </h:column> 
                    <h:column>
                        <f:facet name="header">Cargo</f:facet>
                            #{usuario.office}
                    </h:column> 

                    <h:column>
                        <f:facet name="header">Telefone</f:facet>
                            #{usuario.celular}
                    </h:column> 

                    <h:column>
                        <f:facet name="header">E-mail</f:facet>
                            #{usuario.email}
                    </h:column> 

                </h:dataTable>

            </h:form>
        </div>
        #{usuario.id}
        <div class="divBaixo indigo lighten-2"></div>
    </div>
</h:body>

BEAN

@ManagedBean(name = "BeanUsers")
@RequestScoped
public class BeanUsers {

    private Users usuario = new Users();
    private String confirmarSenha;
    private List<Users> lista;
    private HtmlDataTable dataTable;

    public List<Users> listar() {
        if (this.lista == null) {
            UsersBO usersBO = new UsersBO();
            this.lista = usersBO.listar();
        }

        return this.lista;
    }

    public String users() {

        return "/publico/users";
    }

    public String cadastrar() {
        this.usuario = new Users();
        this.usuario.setAtivo(true);
        return "/publico/cadUsers";
    }

    public String salvar() {
        FacesContext context = FacesContext.getCurrentInstance();

        String senha = this.usuario.getSenha();
        if (!senha.equals(this.confirmarSenha)) {
            FacesMessage facesMessage = new FacesMessage("A senha nao foi confirmada corretamente");
            context.addMessage(null, facesMessage);
            return null;
        }

        UsersBO usersBO = new UsersBO();
        usersBO.salvar(this.usuario);

        return "/publico/users";
    }

    public Users getUsuario() {
        return usuario;
    }

    public void setUsuario(Users usuario) {
        this.usuario = usuario;
    }

    public String getConfirmarSenha() {
        return confirmarSenha;
    }

    public void setConfirmarSenha(String confirmarSenha) {
        this.confirmarSenha = confirmarSenha;
    }

    public String editar() {

       this.usuario = usuario.getSelectedItem();
        this.confirmarSenha = this.usuario.getSenha();

        return "/publico/cadUsers";
    }

    public void setSelectedItem(ValueChangeEvent event) {

        usuario = (Users) dataTable.getRowData();

    }

    public void getSelectedItem() {

        ArrayList<Users> selectedDataList = new ArrayList<Users>();
        selectedDataList.add(usuario);


    }

    ;



         public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }
}

JS

function selectOneRadio(radio) {
var id = radio.name.substring(radio.name.lastIndexOf(':'));
var el = radio.form.elements;
for (var i = 0; i < el.length; i++) {
    if (el[i].name.substring(el[i].name.lastIndexOf(':')) == id) {
        el[i].checked = false;
    }
}
radio.checked = true;
}
  • I did not understand the part of JS. If it is radio button, everyone should have the same name and only 1 should be selected. What is this function then selectOneRadio(radio)?

2 answers

0


An important detail in your Datatable and selectOneRadio, is that the way it was encoded, a radio will be generated for each row of the table, so this does not prevent the user to select more than one record, but it seems that its function javascript selectOneRadio has the goal of "correcting" this situation, but it was kind of, forgive the expression, a wicked gambiarra.

Perhaps it would be better to reassess this approach, I do not know what technologies used in your project, but Primefaces has a Datatable with radio selection, which would serve as a glove for your case, you can see the example here.

A serious problem generated by this approach is that selectOneRadio is linked with the user attribute of your Bean, but as mentioned above, for each row of the table a radio will be generated, and in the end all generated radios are linked to the same user attribute of your Bean, Can you see the problem? For example, let’s assume that in your bean there is an attribute String called test, and that you linked this attribute to two inputText on the same page, which of the values filled by the user (the value of the first or second inputText) will be passed to the test attribute in the back end()?? Realized that the values you will receive in the back end can present an unexpected behavior?

But assuming you don’t want or can’t use Primefaces, and you don’t want to change the approach, I suggest using ajax explicitly, and passing the value of the var from the datatable to the ajax System, however from this approach, is the need for a converter, and we still have the situation discussed in the previous paragraph to be resolved, but moving forward, it would be something like this:

Converter

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import org.apache.commons.lang3.StringUtils;
    @FacesConverter(value = "ConversorUsers")
    @ManagedBean(eager = true)
    @ApplicationScoped
    public class ConversorUsers implements Converter {

        @Override
        public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
            if (StringUtils.isNotBlank(value)) {
                return (Users) uic.getAttributes().get(value);
            }
            return null;
        }

        @Override
        public String getAsString(FacesContext fc, UIComponent uic, Object o) {
            if (o instanceof Users) {
                Users entidade = (Users) o;
                if (entidade instanceof Users && entidade.getId() != null) {
                    uic.getAttributes().put(entidade.getId().toString(), entidade);
                   return entidade.getId().toString();
                }
            }
            return "";
        }    
    }

For more details about converters recommend these links:
Algaworks
Mkyoung
Tutorialspoint

XHTML

<h:column>
  <h:selectOneRadio value="#{BeanUsers.usuario}"  converter="ConversorUsers" onclick="selectOneRadio(this)">
    <f:selectItem    itemValue="#{usuario}"  />
    <f:ajax event="change" listener="#{BeanUsers.setSelectedItem(usuario)}" />
  </h:selectOneRadio>

The convert attribute was added to radio, with the name specified in the @Facesconverter annotation of the respective class. In the ajax Listener you can pass the user variable (the var of the datatable) straight as argument for the setSelectedItem method, and the attribute valuechangelistener of the radio has been removed.

Bean

I’m just posting the changes.

private Users usuario = new Users();
 //adicionando um novo atributo usuarip
 private Users usuarioSelecionado = new Users();
//modificando o metodo para receber um Usuario
 public void setSelectedItem(Users u) {    
    usuarioSelecionado  = u;    
 }

Note that the user attributeSelected is not referenced in xhtml, so we guarantee that it will always have the value that is assigned by the setSelectedItem method, which in turn obtains a radio/dataTabel user. If there was only one radio on the page, you could link userSubjected with the value of selectOneRadio, but since the latter was generated several times, I used this approach to avoid the problem described in the third paragraph.

Remembering, (yes I know I’m being repetitive) that it would be highly recommended to review the approach of this screen/page of its application, due to the above mentioned problems.

  • Okay, very good your approach I will test the solution that Voce passed and see if the first Aces can be ultimalized in the application without major problems.

-1

Functional example:

public void setSelectedItem(ValueChangeEvent event) {
     FacesContext context = FacesContext.getCurrentInstance();
     selectedItem = context.getApplication().evaluateExpressionGet(context, "#{usuario}", User.class);
}
  • the solution presented does not solve.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.