validation: Expression 'command.InternalNotes&validate' is not compatible with the validate binding-behavior.

Hi,

I’m new to this library, using the latest version (both of aurelia framework & validation). My configuration is skeleton navigation typescript with webpack.

My class is configured as following:

import { autoinject, newInstance } from 'aurelia-framework';
import { OrderService } from '../order-service';
import { Router } from 'aurelia-router';
import { ValidationController, ValidationRules  } from 'aurelia-validation';
import { BootstrapFormRenderer  } from '../../resources/validation/bootstrap-form-renderer';

@autoinject
export class OrderSetInternalNotes {

    heading: string = 'Set internal notes';
    command: any = null;

    constructor(private orderService: OrderService,
                private router: Router,
                @newInstance(ValidationController) private validationController: ValidationController) {

        this.validationController.addRenderer(new BootstrapFormRenderer());

    }

    activate(params) {
        this.orderService.getSetInternalNotes(params.id, params.timestamp).then(getSetInternalNotesResponse => {
            if (!getSetInternalNotesResponse.Meta.Success) {
                this.cancel();
            }
            this.command = getSetInternalNotesResponse.Results[0];
            ValidationRules
                .ensure('InternalNotes').required().maxLength(5)
                .on(this.command);
        });
    }

    async execute() {
        let errors = await this.validationController.validate();
        if (errors.length > 0){
            return;
        }
        let getSetInternalNotesResponse = await this.orderService.setInternalNotes(this.command);
        if (!getSetInternalNotesResponse.Meta.Success) {
            return;
        }
        this.close();
    }

    cancel() {
        this.close();
    }

    private close() {
        this.router.navigateToRoute('orderList');
    }

}

the object “command” is gathered from the server and then I’d like to attach the validation when ready.

here is the html

<template>

  <section class="au-animate">
    <h2>${heading}</h2>
    <form role="form" submit.delegate="execute()">
      <div class="form-group">
        <label for="internalNotes">Intenal notes</label>
        <textarea class="form-control"
                  rows="12"
                  value.bind="command.InternalNotes & validate"
                  id="internalNotes"></textarea>
      </div>
      <button type="submit" class="btn btn-primary">Ok</button>
      <button click.delegate="cancel()" class="btn btn-default">Cancel</button>
    </form>
  </section>

</template>

Am I doing something wrong?

Thanks for any advice! Enrico

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 31 (3 by maintainers)

Commits related to this issue

Most upvoted comments

Yep, was able to reproduce this. It goes wrong here:

while (expression instanceof BindingBehavior || expression instanceof ValueConverter) {
  expression = expression.expression;
}

An expression of type BindingBehavior comes in but expression instanceof BindingBehavior evaluates to false.

It appears that 1.7.1 is stored in the lockfile as a redirect from ^1.0.0 and 2.0.0 is stored as a separate entry. The Aurelia libraries depending on aurelia-binding all get their own reference to 1.7.1.

So you get this effect:

aurelia-binding@^2.0.0 image

aurelia-binding@^1.7.1 image

aurelia-binding@^1.7.1 image

aurelia-templating-binding loads its own version to parse the expressions, aurelia-validation also loads its own version to compare the constructors. They’re both 1.7.1 (2.0.0 isn’t even loaded) but different instances, so the constructor functions don’t match up.

1.7.1 being loaded doesn’t really surprise me though - that’s semantic versioning doing its job. I guess the dependency on aurelia-binding needs to be changed to “^1.0.0 | ^2.0.0”.

What does baffle me is that each library loads its own unique instance, even of the same version. At the very least should the same 1.7.1 instance be reused so this sort of thing doesn’t happen. I’d argue that’s a webpack issue, but I’m not entirely sure.

In any case, mismatches in versions like this will always cause problems when using instanceof. The mismatch really has to be avoided.

@bigopon @EisenbergEffect

@fkleuver bringing this to your attention

I am not sure if this is helpful but I ran a working version next to a failing version and I see some differences in what ValidateController passes to getPropertyInfo.

Working version: expression.constructor.name – returns “AccessMember”

Non-working version: expression.constructor.name – returns “BindingBehavior” I can see expression.expression.constructor.name is “AccessMember”

As an experiment I changed getPropertyInfo in the failing version look for expression.expression and at a high level validation seems to work. It could probably have used expression.expression instanceof but this was just a proof of concept. Of course, I have don’t really know how it is supposed to be working but maybe this helps figure out the root cause of this error.

export function getPropertyInfo(expression, source) { var originalExpression = expression; while (expression instanceof BindingBehavior || expression instanceof ValueConverter) { expression = expression.expression; } var object; var propertyName; if (expression instanceof AccessScope) { object = getContextFor(expression.name, source, expression.ancestor); propertyName = expression.name; } else if (expression.expression.constructor.name === “AccessScope”) { object = getContextFor(expression.expression.name, source, expression.expression.ancestor); propertyName = expression.expression.name; } else if (expression instanceof AccessMember) { object = getObject(originalExpression, expression.object, source); propertyName = expression.name; } else if (expression.expression.constructor.name === “AccessMember”) { object = getObject(originalExpression.expression, expression.expression.object, source); propertyName = expression.expression.name; } else if (expression instanceof AccessKeyed) { object = getObject(originalExpression, expression.object, source); propertyName = expression.key.evaluate(source); } else if (expression.expression.constructor.name === “AccessKeyed”) { object = getObject(originalExpression.expression, expression.expression.object, source); propertyName = expression.expression.key.evaluate(source); } else { throw new Error(“Expression '” + originalExpression + “’ is not compatible with the validate binding-behavior.”); } if (object === null || object === undefined) { return null; } return { object: object, propertyName: propertyName }; }

I am also running into this issue after upgrading to aurelia-binding 2.0.0 while upgrading to webpack 4. I downgraded to 1.7.1, deleted my node_modules folder and package-lock.json and reran npm install. I am still getting the same error. Using webpack 4.8.3, npm 6.0.1 various version of aurelia-binding. When I have a little more time, I will bring up a working version and see what is different in the way it checks to see if expression as an instance of AccessMember.

I think I’ve just found the problem: an out-of-date reference to aurelia-binding. In fact I didn’t have an explicit reference to it in package.json.

I’ve just explicitly installed aurelia-binding 1.7.1 and now aurelia-validation 1.1.3 is working for me.

@avrahamcool Does this work for you too?

I’ve just encountered this issue too with aurelia-validation 1.1.3. I’ve just upgraded to Webpack 4, and along with that updated all my other aurelia dependencies. So it’s a little tricky to tell exactly what is the problem.

I tried uninstalling and reinstalling aurelia-validation 1.1.3 but that didn’t help. Neither did trashing my node_modules directory and doing npm install again.

In the end I had to revert to aurelia-validation 1.1.2 which works fine.

I don’t think I’m doing anything unusual with the validation. My setup code is

     this.controller = validationControllerFactory.createForCurrentScope();
     this.controller.addRenderer(new BootstrapFormRenderer());

     ValidationRules
        .ensure('name')
            .required()
        .ensure('moreDetailsLink')
            .displayName("More Details Link")
            .matches(/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/)
            .withMessage("More details link must be a valid url")
        .ensure('shortDescription')
            .displayName("Short Description")
        .satisfies((value, object : any) =>
            !object.includeInPrintEdition || StringUtilities.CountWords(value) <= 30)
            .withMessage("Short Description must be fewer than 30 words")
        .on(EditEventDialogViewModel);

@enrico-padovani I would suggest you to clear node_modules first and re-install

@enrico-padovani so, I have fixed this issue, this worked for me:

npm uninstall aurelia-validation --save
npm install aurelia-binding --save
npm install aurelia-validation --save