0

I created a simple converter, I am reading a book, and the code below should work, but when I select an item it is not being set as the value. I placed a break point on the setter and it's not being hit when select an item in the selectOneMenu.

<?xml version='1.0' encoding='UTF-8' ?>
<!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"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title></title>
    </h:head>
    <h:body>
        <h:form>
            dfdfd
            <p:selectOneMenu value="#{selecaoController.selectedTag}" var="t"
                             converter="tagConverter">
                
                <f:selectItem itemLabel="Select One" itemValue="" />
                <f:selectItems value="#{selecaoController.tagPojos}" var="tag"
                               itemLabel="#{tag.label}" itemValue="#{tag}" />
                <p:column>
                    #{t.label} - #{t.value}
                </p:column>
                <p:column>
                    <p:graphicImage value="/resources/images/tags/#{t.value}.png"
                                    width="32px" height="32px"/>
                </p:column>
                
                <p:ajax event="change" process="@this" update="msg" />
                
            </p:selectOneMenu>
     
            <p:outputLabel id="msg" value="#{selecaoController.selectedTag.label}" />
            
        </h:form>
    </h:body>
</html>

classe.

package com.packtpub.pfbg.controllers;


import java.util.ArrayList;
import java.util.List;
import javax.faces.application.FacesMessage;
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;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author diego
 */

@FacesConverter(value = "tagConverter")
public class TagConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        
       if(value == null || value.trim().equals("")){
           return null;
       } 
       try{
           Tag t1 = new Tag(1, "JavaScript", "javascript");
           Tag t2 = new Tag(2, "C#", "C#");
          Tag t3 = new Tag(3, "Java", "Java");
          Tag t4 = new Tag(4, "Angular", "angular");


           List<Tag> ts = new ArrayList<Tag>();
           ts.add(t1);
           ts.add(t2);
           ts.add(t3);
           ts.add(t4);

           int id = Integer.parseInt(value);
           List<Tag> tags = ts;
           
           for(Tag t : tags){
               
               if(t.getId() == id){
                   return t;

               }
           }         
       }
        catch(NumberFormatException ex){
              throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "conversion erro", "Not a valid tag"));
          }
       return null;
    }

    
    
    
    

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        
        if(value == null || value.equals("")){
            return "";
        }else{
            return String.valueOf(((Tag) value).getId());
        }
        
    }
    
}

outra classe

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.packtpub.pfbg.controllers;

import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

/**
 *
 * @author diego
 */

@ManagedBean
@RequestScoped
public class SelecaoController {
    
  private List<Tag> tagPojos;
  private Tag selectedTag;
    
   public SelecaoController(){
       
       tagPojos = new ArrayList<Tag>();
       tagPojos.add(new Tag(1, "JavaSE", "java-se", "Java Programming Language"));
       tagPojos.add(new Tag(2, "JavaEE", "javaEE", "Java Enterprise"));
       tagPojos.add(new Tag(3, "Spring", "Spring", "Spring Framework"));

   } 

    public List<Tag> getTagPojos() {
        return tagPojos;
    }

    public void setTagPojos(List<Tag> tagPojos) {
        this.tagPojos = tagPojos;
    }

    public Tag getSelectedTag() {
        return selectedTag;
    }

    public void setSelectedTag(Tag selectedTag) {
        this.selectedTag = selectedTag;
    }
   
   
    
}
Diego Alves
  • 2,462
  • 3
  • 32
  • 65

1 Answers1

1

If you add a growl or a message for your field or raise your log level you'll see that after select an item you're getting this error:

Validation Error: Value is not valid

The problem is that the selected value isn't in the list. The jsf code that searches in the list iterate all the children of the selectOneMenu and checks if the element returned from the converter is equal to any of them.
You have many ways to make your code works:

  1. Since you're using another list, you can override the equals method in your Tag class, eg checking only the id value, if it's the key, in order to get the match even without having the same objects

  2. Iterate, in the converter, the same list, to return the exact same object

For solution 2, if you move your controller to view scope, this code works, but there's also a way directly from component variable and also from request scope.

Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
SelecaoController viewScopedBean = (SelecaoController) viewMap.get("selecaoController");
for (Tag t : viewScopedBean.getTagPojos()) {
    if (t.getId() == id) {
        return t;
    }
}
WoAiNii
  • 1,003
  • 1
  • 11
  • 19