validation icon indicating copy to clipboard operation
validation copied to clipboard

Binding behaviors "validate" and "updateTrigger:'blur'" don't mix

Open RomkeVdMeulen opened this issue 7 years ago • 12 comments

I'm submitting a bug report

  • Library Version: 1.0.0

  • Browser: Chrome 55

Current behavior: When applying both the updateTrigger:'blur' and validate binding behaviors to a binding, the value is validated before it is updated.

See https://gist.run/?id=c533e53e62cb348cc96aa9445bae612a and note when entering characters and blurring the input the validated value is always the previously entered value.

Expected/desired behavior: The validation should only run after the source value has been updated. This should also work when using validateOnBlur rather than validate in the same scenario. I'm not sure how something like value.bind="myVal & updateTrigger:'blur' & validateOnChange" should be handled - perhaps a warning against this in the documentation would suffice.

RomkeVdMeulen avatar Mar 21 '17 11:03 RomkeVdMeulen

@RomkeVdMeulen I don't see updateTrigger:'blur' in the gist.

jdanyow avatar Mar 25 '17 16:03 jdanyow

Hmm, seems that when on gist.run I fork the gist mentioned in the issue template, it overwrites any previous fork of the same gist I already had. You were looking at the gist I wrote for that doc section.

I've manually recreated and cloned the gist, so hopefully this one won't be overwritten: https://gist.run/?id=90009f5381244e168efcfe46e8c886ac

RomkeVdMeulen avatar Mar 27 '17 09:03 RomkeVdMeulen

Any suggestions on this? It's blocking our adoption of aurelia-validation.

RomkeVdMeulen avatar Apr 03 '17 07:04 RomkeVdMeulen

Haven't looked at this yet. Have you tried the validateOnBlur binding behavior in place of the validate binding behavior?

jdanyow avatar Apr 03 '17 18:04 jdanyow

I have: same result.

RomkeVdMeulen avatar Apr 04 '17 06:04 RomkeVdMeulen

Hi @RomkeVdMeulen, I tried this with validateOnBlur and validation occurred with the newly entered value.

      <input type="text" class="form-control" id="first" placeholder="Input"
             value.bind="firstName & validateOnBlur">

Here is a gist which (I believe) gives the behaviour you want?

Admittedly, the model does not get updated on blur with this so may still not be what you want.

Edit After modifying to

      <input type="text" class="form-control" id="first" placeholder="Input"
             value.bind="firstName & updateTrigger:'blur' & validateOnBlur">

I get the same result, the old value gets validated, not the new one.

alastair-mcdonald avatar Apr 04 '17 08:04 alastair-mcdonald

@alastair-mcdonald The updateTrigger:'blur' is important. I tried your gist with the modification and saw the same behavior: old value is validated.

Results probably vary by browser. Both behaviors add an event handler to the blur event, and AFAIK it's up to the browser to decide which to call first. Some may see the new value being validated, some the old one.

Is this something Aurelia can solve? It's going to be difficult to have two listeners to the same event always being called in a particular order.

RomkeVdMeulen avatar Apr 04 '17 11:04 RomkeVdMeulen

@RomkeVdMeulen Perhaps Aurelia could hook up a single event handler for blur which specifies all the behaviours which are to be carried out by the blur event, so enabling Aurelia to control sequence. Not sure how much of a change that would require internally for Aurelia though; possibly a breaking change needed.

alastair-mcdonald avatar Apr 04 '17 12:04 alastair-mcdonald

I've decided to hack around this problem. In my case I was using it like this:

<input value.bind="myVal & updateTrigger:'blur' & myNormalisation & validate"/>

The intention here was to normalise the user-entered value on blur and, if necessary, update the input with the normalised value. To ensure the normalised value is validated, I'm manually triggering another blur event after updating the input in my binding behaviour:

const updateSource = binding.updateSource.bind(binding);
binding.updateSourceOriginal = binding.updateSource;
binding.updateSource = function(value: any) {
	const normal = normalise(value);
	updateSource(normal);

	if (normal !== value) {
		/* Update view to normalised value */
		this.updateTarget(normal);

		/* Trigger blur to ensure other listeners, like validation,
		 * are triggered again on the normalised value. */
		binding.target.dispatchEvent(new FocusEvent("blur"));
	}
};

Not ideal, but at least I can finally proceed.

RomkeVdMeulen avatar May 02 '17 13:05 RomkeVdMeulen

I'm seeing a similar problem with this binding: <input type="text" value.bind="xyz & debounce:600 & validate" /> and on my viewModel: this.controller.validateTrigger = validateTrigger.blur;

If I type and blur quick enough, an old value is validated - sometimes even the empty value before I started typing! Then if I focus the input and blur it again, the correct value is validated.

thinkOfaNumber avatar Jun 19 '17 01:06 thinkOfaNumber

Any plans for fixing this issue? Will aurelia@next handle it correctly?

rdemetrescu avatar Jun 27 '19 15:06 rdemetrescu

As a workaround for when I am using a Value Converter with udpateTrigger:'blur', I replace validate with validateManually, and then use blur.trigger to call a method that manually calls validate for this property.

View: <input class type="text" value.bind="value1 | valueConverter & updateTrigger:'blur' & validateManually" blur.trigger="validate('value1')">

ViewModel: validate(propertyName) { this.validationController.validate({object: this, propertyName: propertyName}); }

But would be great if & updateTrigger:'blur' & validate could work as-is.

alexisszabo avatar Oct 28 '20 07:10 alexisszabo