Edit with Radio button in jsf

0

Well, I'm starting to develop with JSF and I'm having a question about how to do it for my method. edit receive the right object from the radio button, the way it's implemented it always takes the first one from the table and not the one selected by the radio, what I did not see?

  

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;
}
    
asked by anonymous 20.01.2018 / 15:02

2 answers

0

An important detail in your DataTable and selectOneRadio is that in the way it was coded, a radio will be generated for each row of the table, so this does not prevent the user from selecting more than one record, but it seems that the its selectOneRadio javascript function aims to "fix" this situation, but this got kinda, forgive me the expression, a damn gambiarra.

Perhaps it would be better to re-evaluate this approach, I do not know which 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 the selectOneRadio is linked to the Bean user attribute, but as mentioned above, for each row of the table a radius 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 a String named test , and that you linked this attribute to two inputText on the same page, which of the values populated by the user (the value of the first or the second inputText) that will be passed to the test attribute in the back end (Bean)? Have you noticed that the values that you will receive in the back end may behave unexpectedly?

But assuming you do not want or can not use PrimeFaces, and do not want to change the approach, I suggest using ajax explicitly, and passing the value of the var from dataTable to the ajax listener, but that approach is the need for a converter, and we still have the situation discussed in the previous paragraph to be resolved, but moving on, it would look 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 on converters I 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 on the radio was added, with the name specified in the @FacesConverter annotation of its class. In the ajax listener you can pass the user variable (the dataTable var) as an argument to the setSelectedItem method, and the valueechangelistener attribute of the radius 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 userSelected attribute 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 gets a user from the radius / dataTabel. If on the page there was only one radio, you could link userSelected direct with the value of selectOneRadio, but as the latter was generated several times, I used this approach to avoid the problem described in the third paragraph.

By remembering, ( yes I know I'm being repetitive ) it would be highly recommended to review the approach to this screen / page of your application, due to the problems mentioned above.     

26.01.2018 / 16:26
-1

Functional example:

public void setSelectedItem(ValueChangeEvent event) {
     FacesContext context = FacesContext.getCurrentInstance();
     selectedItem = context.getApplication().evaluateExpressionGet(context, "#{usuario}", User.class);
}
    
22.01.2018 / 17:43