Combobox validation

Hello.

I have a form with a combobox loaded from DDBB.


(...)
       // Item container para combobox de conceptos
		containerConcepto = new BeanItemContainer<ConceptoVO>(ConceptoVO.class);
        for (ConceptoVO conceptoItem : modelLocator.conceptoList) {
        	containerConcepto.addItem(conceptoItem);
        }
(...)        

I use a FormFieldFactory form my form with Override createField method:


(...)
		partidaForm.setFormFieldFactory(new FormFieldFactory() {

			(...)
		    
			@Override
			public Field createField(Item item, Object propertyId, Component uiContext) {
				AbstractTextField field;
				
		    	boolean enabled = ( (Integer) item.getItemProperty("id").getValue() > 0
		    			|| isNew);
		    	
		        if ("numeroFactura".equals(propertyId)) {
		        	(...)
		        } else if ("observaciones".equals(propertyId)) {
		            (...)
		        } else if ("concepto".equals(propertyId)) {
		        	// Create a selection component bound to the container
		            ComboBox nombreConcepto = new ComboBox("Concepto");
		        	[b]
nombreConcepto.addValidator(new NombreConceptoValidator());
[/b]
		            nombreConcepto.setEnabled(enabled);
		            nombreConcepto.setNullSelectionAllowed(false);
		            Property.ValueChangeListener listener = new Property.ValueChangeListener() {
		        	    public void valueChange(ValueChangeEvent event) {
		        	    	saveButton.setEnabled(partidaForm.isModified());
		        	    	discardChanges.setEnabled(partidaForm.isModified());
		        	    }
		        	};
		        	nombreConcepto.addListener(listener);
		        	[b]
nombreConcepto.setImmediate(true);
[/b]
		            // Set the caption mode to read the caption directly
		            // from the 'name' property of the bean
		            nombreConcepto.setItemCaptionPropertyId("nombre");
		        	nombreConcepto.setItemCaptionMode(
		                    Select.ITEM_CAPTION_MODE_PROPERTY);
		        	nombreConcepto.setContainerDataSource(containerConcepto);
		        	
		            nombreConcepto.requestRepaint();
		            
		        	return nombreConcepto;
		        } else {
		        	field = null;
		        }
		        
		        (...)

		        return field;
			}
				
		});
(...)

I add a validator to combobox:


@SuppressWarnings("serial")
public class NombreConceptoValidator implements Validator {
	
	public NombreConceptoValidator() {
	}
	
	@Override
	public void validate(Object value) throws InvalidValueException {
		if (!isValid(value)) {
			if (value != null) {
				throw new InvalidValueException(
						"Por favor, seleccione un concepto.");
			}
        }
	}

	@Override
	public boolean isValid(Object value) {
		if (value == null || !(value instanceof ConceptoVO)
				|| new Integer(0).equals( ((ConceptoVO) value).getId() ) ) {
            return false;
        }

        return true;
	}
}

but not work.

No validators executed for my combobox. The other fields in form are validated. Any ideas?

(Sorry for my poor english)

If you don’t want to acceppt empty values (null), set your field required.

Thanks for your reply Tobias.

But my problem is the validation not fired, NombreConceptoValidator is never executed.

An empty non-required field doesn’t get validated by purpose.

Ok, with setRequired this filed execute that validation (required):


                      (...)
                      } else if ("concepto".equals(propertyId)) {
		        	// Create a selection component bound to the container
		            ComboBox nombreConcepto = new ComboBox("Concepto");
		        	[b]
nombreConcepto.setRequired(true);
[/b]
		        	nombreConcepto.setRequiredError("Por favor, añada el campo " + DefaultFieldFactory.createCaptionByPropertyId(propertyId));
		            nombreConcepto.setEnabled(enabled);
		            nombreConcepto.setNullSelectionAllowed(false);
		            Property.ValueChangeListener listener = new Property.ValueChangeListener() {
		        	    public void valueChange(ValueChangeEvent event) {
		        	    	saveButton.setEnabled(partidaForm.isModified());
		        	    	discardChanges.setEnabled(partidaForm.isModified());
		        	    }
		        	};
		        	nombreConcepto.addListener(listener);
		        	nombreConcepto.setImmediate(true);
		            // Set the caption mode to read the caption directly
		            // from the 'name' property of the bean
		            nombreConcepto.setItemCaptionPropertyId("nombre");
		        	nombreConcepto.setItemCaptionMode(
		                    Select.ITEM_CAPTION_MODE_PROPERTY);
		        	nombreConcepto.setContainerDataSource(containerConcepto);
		        	
		            nombreConcepto.requestRepaint();
		            
		        	return nombreConcepto;
		        }
                        (...)

But I don´t know why in this case the validation (required) not executed…


                        (...)
		        } else if ("tipoConcepto".equals(propertyId)) {
		        	ComboBox tipoConcepto = new ComboBox("Tipo concepto");
		        	tipoConcepto.setRequired(true);
		        	tipoConcepto.setRequiredError("Por favor, añada el campo " + DefaultFieldFactory.createCaptionByPropertyId(propertyId));
		        	tipoConcepto.setEnabled(enabled);
		        	tipoConcepto.setNullSelectionAllowed(false);
		            Property.ValueChangeListener listener = new Property.ValueChangeListener() {
		        	    public void valueChange(ValueChangeEvent event) {
		        	    	saveButton.setEnabled(conceptoForm.isModified());
		        	    	discardChanges.setEnabled(conceptoForm.isModified());
		        	    }
		        	};
		            tipoConcepto.addListener(listener);
		            tipoConcepto.setImmediate(true);
		            [b]
for (TipoConceptoSelectItem<?> tc : tipoConceptos) {
		            	tipoConcepto.addItem(tc.getValue());
		            	tipoConcepto.setItemCaption(tc.getValue(), tc.getCaption());
		            }
		            tipoConcepto.setItemCaptionMode(ComboBox.ITEM_CAPTION_MODE_EXPLICIT);
[/b]
		            tipoConcepto.requestRepaint();
		            
		            return tipoConcepto;
		        }
                        (...)

The only thing that changes is the combobox container:


			final ArrayList<TipoConceptoSelectItem<?>> tipoConceptos =
					new ArrayList<TipoConceptoSelectItem<?>>(
						    Arrays.asList(
						    		new TipoConceptoSelectItem<Integer>("Ingreso", 1),
						    		new TipoConceptoSelectItem<Integer>("Gasto", 2)));

Class TipoConceptoSelectedItem:


public class TipoConceptoSelectItem<T> {
	
	String caption;
	T value;
	
	public TipoConceptoSelectItem(String caption, T value) {
		super();
		this.caption = caption;
		this.value = value;
	}

	public String getCaption() {
		return caption;
	}

	public void setCaption(String caption) {
		this.caption = caption;
	}

	public T getValue() {
		return value;
	}

	public void setValue(T value) {
		this.value = value;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((caption == null) ? 0 : caption.hashCode());
		result = prime * result + ((value == null) ? 0 : value.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;
		TipoConceptoSelectItem other = (TipoConceptoSelectItem) obj;
		if (caption == null) {
			if (other.caption != null)
				return false;
		} else if (!caption.equals(other.caption))
			return false;
		if (value == null) {
			if (other.value != null)
				return false;
		} else if (!value.equals(other.value))
			return false;
		return true;
	}
	
}

Validation required never is executed.

I don´t quite understand why it happens…

Thanks for reply

Validation will only be executed as result of an user-action. The fat printed lines in your code-example are just modifying the container and won’t trigger the validation as that would be kind of weird in most cases.