You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by "Thiago H. de Paula Figueiredo" <th...@gmail.com> on 2009/12/23 20:59:47 UTC

Example of overriding the default ValidationDecorator

Hi!

I'd never tried to override the default ValidationDecorator.
It adds the "invalid-field" CSS class to fields that have validation  
errors and to their labels. For each required field, it adds an asterisk  
after its label. In addition, it writes the error message after the field  
inside a <span class="error-description">
I've just did it and this is the code:

public class OtherValidationDecorator extends BaseValidationDecorator {

	private final Environment environment;

	private final MarkupWriter markupWriter;

	public OtherValidationDecorator(Environment environment, MarkupWriter  
markupWriter) {
		this.environment = environment;
		this.markupWriter = markupWriter;
	}

	@Override
	public void insideField(Field field) {
		if (inError(field)) {
			addErrorClassToCurrentElement();
		}
	}

	@Override
	public void afterField(Field field) {

		System.out.println(field.getControlName());
		if (inError(field)) {

			ValidationTracker tracker = getTracker();
			markupWriter.element("span", "class", "error-description");
			markupWriter.write(tracker.getError(field));
			markupWriter.end();

		}

	}

	@Override
	public void insideLabel(Field field, Element element) {
		if (field == null)
			return;

		if (inError(field)) {
			addErrorClassToCurrentElement();
		}
		if (field.isRequired()) {
			element.text("*");
		}

	}

	private boolean inError(Field field) {
		ValidationTracker tracker = getTracker();
		return tracker.inError(field);
	}

	private ValidationTracker getTracker() {
		return environment.peekRequired(ValidationTracker.class);
	}

	private void addErrorClassToCurrentElement() {
		markupWriter.getElement().addClassName("invalid-field");
	}

}

In AppModule:


public static void contributeMarkupRenderer(
		OrderedConfiguration<MarkupRendererFilter> configuration, final  
Environment environment) {

	MarkupRendererFilter validationDecorator = new MarkupRendererFilter() {

		public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer) {
			ValidationDecorator decorator = new  
OtherValidationDecorator(environment, writer);

			environment.push(ValidationDecorator.class, decorator);
			renderer.renderMarkup(writer);
			environment.pop(ValidationDecorator.class);
				
		}
	};
		
	configuration.override("DefaultValidationDecorator", validationDecorator);

}

-- 
Thiago H. de Paula Figueiredo
Independent Java, Apache Tapestry 5 and Hibernate consultant, developer,  
and instructor
Owner, software architect and developer, Ars Machina Tecnologia da  
Informação Ltda.
http://www.arsmachina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


RE: Example of overriding the default ValidationDecorator

Posted by "Blower, Andy" <An...@proquest.co.uk>.
> Unfortunately it seems that it does not help against these error-
> bubbles.

To override the client side you'll need to read tapestry.js and follow some of what it does. Personally I feel that the error bubbles should not be part of the T5 core, but an optional example validation module.

I created an inline validation decorator which puts the validation messages inside the field labels (for accessibility reasons) and overrode parts of tapestry.js in a js file added in our page layout so it comes on every page. Removing and changing the client side validation functions. Compare with the std tapestry.js versions and hopefully it will help you.

The js looks like this:

Tapestry.FormEventManager.addMethods(
{
	initialize : function(form)
	{
		this.form = $(form);

		this.form.onsubmit = this.handleSubmit.bindAsEventListener(this);
	},

	handleSubmit : function(domevent)
	{
		var t = $T(this.form);

		t.validationError = false;

		this.form.fire(Tapestry.FORM_PREPARE_FOR_SUBMIT_EVENT, this.form);

		// This flag can be set to prevent the form from submitting normally.
		// This is used for some Ajax cases where the form submission must
		// run via Ajax.Request.

		if (this.preventSubmission)
		{
			// Prevent the normal submission.

			Event.stop(domevent);

			// Instead ...

			this.form.fire(Tapestry.FORM_PROCESS_SUBMIT_EVENT);

			return false;
		}

		// Validation is OK, not doing Ajax, continue as planned.

		return true;
	}
});

Tapestry.FieldEventManager.addMethods(
{
	initialize : function(field)
	{
		this.field = $(field);

		var id = this.field.id;
		this.label = $(id + '-label');
        	this.icon = $(id + '-icon');

		this.translator = Prototype.K;

		document.observe(Tapestry.FOCUS_CHANGE_EVENT, function(event)
		{
			// If changing focus *within the same form* then perform validation.
			// Note that Tapestry.currentFocusField does not change
			// until after the FOCUS_CHANGE_EVENT notification.
			if (Tapestry.currentFocusField == this.field && this.field.form == event.memo.form) {
				this.validateInput();
			}
		}.bindAsEventListener(this));
	},

	// Removes validation decorations if present.
	removeDecorations : function()
	{
		this.field.removeClassName("t-error");

		if (this.label) {
			this.icon.hide();
			this.label.insert(this.icon);
			var errorMsgId = this.field.id + ':error';
			if (!this.errorMessage) {
				this.errorMessage = $(errorMsgId);
			}
			if (this.errorMessage) {
				Element.remove(this.errorMessage);
				this.errorMessage = null;
			}
		}
	},

	/**
	 * Show a validation error message, which will add decorations to the
	 * field and it label.
	 * @param message validation message to display
	 */
	showValidationMessage : function(message)
	{
		$T(this.field).validationError = true;
		$T(this.field.form).validationError = true;
		this.field.addClassName("t-error");

		if (this.label)	{
			var errorMsgId = this.field.id + ':error';
			if (!this.errorMessage) {
				this.errorMessage = $(errorMsgId);
			}
			if (!this.errorMessage) {
				this.errorMessage = new Element('span', {'id': errorMsgId, 'class': 't-error'});
				this.label.insert({ bottom: this.errorMessage});
			}
			this.errorMessage.update(message);
			this.errorMessage.insert({top: this.icon});
			this.icon.show();
		}
	}
});


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Example of overriding the default ValidationDecorator

Posted by Piero Sartini <li...@pierosartini.de>.
Thanks Thiago, that helped me a lot.
Unfortunately it seems that it does not help against these error-bubbles.

       Piero

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Example of overriding the default ValidationDecorator

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Fri, 03 Aug 2012 04:57:02 -0300, mem <me...@gmail.com>  
wrote:

> value has to parsed, probably ending up in the same situation as i'm now
> with the production mode. So i guess i'm stuck with adding the css  
> classes just manually to the fields.

Instead of implementing a ValidationDecorator, you could implement one or  
more Validators and apply them automatically to fields by contributing a  
ValidationConstraintGenerator. Look at the render() method of Validator:  
you can use it to change the generated Tapestry DOM.

-- 
Thiago H. de Paula Figueiredo

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Example of overriding the default ValidationDecorator

Posted by mem <me...@gmail.com>.
That's what i already thought of too, i was just hoping to be wrong.
I tried all kinds of different approaches, a mixin can't really work as it
should be applied to labels automatically and not manually adding a mixin.
Using a worker i would get there but there're issues with the dynamically
created conduits and it gets really messy with reflection as the parameter
value has to parsed, probably ending up in the same situation as i'm now
with the production mode. So i guess i'm stuck with adding the css classes
just manually to the fields.

Anyways, thanks for the answer.



--
View this message in context: http://tapestry.1045711.n5.nabble.com/Example-of-overriding-the-default-ValidationDecorator-tp2419072p5715029.html
Sent from the Tapestry - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: Example of overriding the default ValidationDecorator

Posted by Josh Canfield <jo...@gmail.com>.
You are probably running into the fact that Tapestry rewrites your
page/component classes so that there is only one instance of the class used
across all requests. To do this all of the property accesses are
intercepted and replaced with ThreadLocal values. When you are in
development mode tapestry shadows the values in the actual class itself so
that you can see them in the debugger.

Check out this fixed issue for more details
https://issues.apache.org/jira/browse/TAP5-1208

Have you considered using a Mixin?
http://tapestry.apache.org/component-mixins.html

Or possibly you could write your own class transformer :
http://tawus.wordpress.com/2011/04/21/plastic-property/

Josh

On Aug 1, 2012 12:22 AM, "mem" <me...@gmail.com> wrote:

> Hello,
>
> hope this Thread is still alive.
> I've used a similar approach to figure out if the label is attached to a
> field which renders a required field. The whole thing is a bit complex as
> we're using JSR303 annotations on the DTO so i've to get the parameter of
> the textField and then evaluate the string. Using reflection i'm checking
> if
> the attribute of the DTO has a NotNull annotation and depending on that i'm
> appending a CSS class which then renders an asterisk.
> Funny thing is that this doesn't work when i'm switching on the Tapestry
> Production Mode. When debugging i found out that all fields in my component
> are null whereas they're the expected objects when not using production
> mode.
> I couldn't figure out why that is, does anyone have an explanation for this
> behavior or any clues where/what to search for?
>
> Thanks in advance.
>
> Matt
>
>
>
> --
> View this message in context:
> http://tapestry.1045711.n5.nabble.com/Example-of-overriding-the-default-ValidationDecorator-tp2419072p5714940.html
> Sent from the Tapestry - User mailing list archive at Nabble.com.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: Example of overriding the default ValidationDecorator

Posted by mem <me...@gmail.com>.
Hello,

hope this Thread is still alive.
I've used a similar approach to figure out if the label is attached to a
field which renders a required field. The whole thing is a bit complex as
we're using JSR303 annotations on the DTO so i've to get the parameter of
the textField and then evaluate the string. Using reflection i'm checking if
the attribute of the DTO has a NotNull annotation and depending on that i'm
appending a CSS class which then renders an asterisk.
Funny thing is that this doesn't work when i'm switching on the Tapestry
Production Mode. When debugging i found out that all fields in my component
are null whereas they're the expected objects when not using production
mode.
I couldn't figure out why that is, does anyone have an explanation for this
behavior or any clues where/what to search for?

Thanks in advance.

Matt



--
View this message in context: http://tapestry.1045711.n5.nabble.com/Example-of-overriding-the-default-ValidationDecorator-tp2419072p5714940.html
Sent from the Tapestry - User mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org