Multiple Fields Required in Form Validation

Hi,

I set up a test scenario where a form has 2 text fields. The only requirement is that the fields cannot both be empty at the same time. So, it’s okay for one field to be empty while the other one is populated. I found out that adding a validator to one (or both) of the fields does not handle this scenario because the validator does not get fired when the field is empty. So, I made up a solution where I set the required flags on both fields to false on the form initialization but conditionally enable the flags when the submit button is clicked (if I detect that both fields are empty). Is this a reasonable/ideal solution to this scenario or is there a better/cleaner way to do this?

Here is the sample code that demonstrates this:



public class MultipleFieldRequiredValidationTestApplication extends Application {

	@Override
	public void init() {
		Window window = new Window("MultipleFieldRequiredValidationTestApplication");
		setMainWindow(window);
		
		final Form form = new Form();
		final TextField textField1 = new TextField("Test 1");
		String commonMessage = "Both Test1 and Test2 fields are required";
		textField1.setRequiredError(commonMessage);
		final TextField textField2 = new TextField("Test 2");
		textField2.setRequiredError(commonMessage);
		form.addField("test1", textField1);
		form.addField("test2", textField2);
		
		// added a validator but the exception never gets fired
		textField1.addValidator(new Validator() {
			
			public void validate(Object value) throws InvalidValueException {
				if (textField1.getValue().equals("") && textField2.getValue().equals("")) {
					throw new InvalidValueException("This never gets thrown because this method doesn't get called when both fields are empty");
				}
			}
			
			public boolean isValid(Object value) {
				if (textField1.getValue().equals("") && textField2.getValue().equals("")) {
					return false;
				}
				return true;
			}
		});
		
		window.addComponent(form);
		
		Button commit = new Button("Commit", new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				textField1.setRequired(false);
				textField2.setRequired(false);
				event.getButton().setComponentError(null);
				
				if (textField1.getValue().equals("") && textField2.getValue().equals("")) {
					textField1.setRequired(true);
					textField2.setRequired(true);
				}
				
				form.commit();
			}
		});
		window.addComponent(commit);
	}

}

I don’t know about ideal but you could also use valuechangelistener to check the values every time either is changed.

I like your solution better…thanks!


public class MultipleFieldRequiredValidationTestApplication2 extends Application {

	@Override
	public void init() {
		Window window = new Window("MultipleFieldRequiredValidationTestApplication");
		setMainWindow(window);
		
		final Form form = new Form();
		final TextField textField1 = new TextField("Test 1");
		String commonMessage = "Test1 and Test2 fields cannot both be empty";
		textField1.setRequiredError(commonMessage);
		final TextField textField2 = new TextField("Test 2");
		textField2.setRequiredError(commonMessage);
		form.addField("test1", textField1);
		form.addField("test2", textField2);
		
		textField1.setRequired(true);
		textField2.setRequired(true);
		
		textField1.addListener(new AnotherFieldRequiredValueChangeListener(textField1, textField2));
		textField2.addListener(new AnotherFieldRequiredValueChangeListener(textField2, textField1));
		
		window.addComponent(form);
		
		Button commit = new Button("Commit", new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				event.getButton().setComponentError(null);
				
				form.commit();
				
				textField1.setRequired(false);
				textField2.setRequired(false);
			}
		});
		window.addComponent(commit);
	}
	private class AnotherFieldRequiredValueChangeListener implements ValueChangeListener {
		private AbstractField anotherField;
		private AbstractField thisField;
		public AnotherFieldRequiredValueChangeListener(AbstractField thisField, AbstractField anotherField) {
			this.anotherField = anotherField;
			this.thisField = thisField;
		}

		public void valueChange(ValueChangeEvent event) {
			String thisValue = (String) event.getProperty().getValue();
			String anotherValue = (String) anotherField.getValue();
			if (!thisValue.equals("") || !anotherValue.equals("")) {
				thisField.setRequired(false);
				anotherField.setRequired(false);
			}
			else {
				thisField.setRequired(true);
				anotherField.setRequired(true);				
			}
		}
	}
}