Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Jason Sobell
    @jsobell
    @tgmendes Well the tricky thing is that validation is against the object, not a field. So what you really are asking is how to get the property that's associated with the field, then look at the ValidationController and find if it is referencing that property, and if so does it have any rules associated with that reference that are of the type you want :)
    I know this isn't what you want to hear, but I'd start with classes such as https://github.com/aurelia/validation/blob/master/src/validate-binding-behavior-base.ts and https://github.com/aurelia/validation/blob/master/src/validation-controller.ts and see if you can see the best approach.
    I worked on the design of this about 2 years ago, but @jdanyow did all the Aurelia coding and all of the binding magic.
    I remember him saying he was going to do a huge doco of how the binding works, and I suspect most of that is now in the official documentation, but I don't think the inner workings of the validation were given the same treatment.
    Eagle94T
    @Eagle94T
    Hi guys,
    I have a problem with the validation and IE11.
    I set the validationTrigger to blurOrChange, but in IE11 everytime the page is loaded, the validation has already take place.
    Since I'm not changing or focusing the value, and it works in chrome and firefox fine, there is an issue with IE11.
    Did anyone have the same problem, or knows how to solve this?
    J├╝rgen Wenzel
    @jwx
    Anyone had the issue that only the first validation work?
    Max
    @MaximBalaganskiy
    May be reset the controller on activate?
    Patrick Walters
    @PWKad
    @Eagle94T did you resolve this? I see the same behavior and am trouble-shooting now
    I may open a bug for tracking
    Patrick Walters
    @PWKad
    aurelia/validation#494
    doktordirk
    @doktordirk
    aurelia/validation#423 ?
    Eagle94T
    @Eagle94T
    @PWKad I wasn't able to fix the problem yet
    Patrick Walters
    @PWKad
    @doktordirk I saw that issue but wasn't sure if it was related.
    jbockle
    @jbockle
    hey everyone I built a plugin for creating forms using JSON schema & aurelia-validation, check it out here https://www.npmjs.com/package/aurelia-json-schema-form
    Charles Lindsay
    @VagyokC4
    @jbockle Looks nice. Is there a generator for the schema / form? i.e. I give it a model and it produces the two required schema's? How does one easily produce the form and schema json?
    jbockle
    @jbockle
    @VagyokC4 Thanks! Still working on creating documentation, you can create JSON schema through several online generators like https://jsonschema.net/. As for the form definition, anything you want to expose on the form works off of matching property keys with your schema. The sample/json-form.ts has an example of how that looks, and the sample/json-schema.ts has an example of its corresponding schema.
    jbockle
    @jbockle
    is there a way I can use display errors on entity validation using a custom renderer?
    jbockle
    @jbockle
    i.e. i have a rule: ValidationRules.ensureObject().. that I also added to controller with .addObject(...)
    I see it come up in render instruction, of course the element is null
    the validation controller is in a parent binding context
    thought of trying instantiating its own controller and displaying errors off of that, but not sure if the parent validation controller would merge errors
    Jameson Strocsher
    @jamesond

    Anyone have a good sample of dynamic rules for dynamic fields where field names could be "custom_1, custom_2" etc.

      this.customRequireds.map((field, index) => {
                        this.rules = [];
                        console.log(field);
                        if (field.required) {
                            console.log(index);
                            field.value = "";
                            console.log(field.bind);
                            this.rules.push(ValidationRules.ensure(field.bind).displayName(field.field_name).required().rules);
                            this.controller.addObject(this.customRequireds[index], this.rules);
    
                        }
                    });
    
    
      <template repeat.for="field of customFields" if.bind="customFields.length > 0">
                            <div class="form-group">
                                <div class="controls row">
                                    <div class="col-md-4">
                                        <label if.bind="allowOrders" for="custom_${field.customer_custom_field_id}">${field.field_name}<span class="textError" show.bind="field.required">*</span>:</label>
                                        <label if.bind="!allowOrders" for="custom_${field.customer_custom_field_id}">${field.field_name}<span class="textError" show.bind="field.requiredApproval">*</span>:</label>
                                        <input type="text" class="form-control" value.bind="field.value & validate:controller" id="custom_${field.customer_custom_field_id}" name="custom_${field.customer_custom_field_id}">
                                    </div>
                                </div>
                            </div>
    
    
                        </template>

    This doesn't seem to be getting me where I need to be. Any help or a good example would be awesome.

    Max
    @MaximBalaganskiy
    @jamesond what are the elements of the customRequireds array?
    and what object you're validating?
    Jameson Strocsher
    @jamesond
    @MaximBalaganskiy Hi Max, customRequireds is an array of objects say {name:theName,value:'',required:true, bind:'custom_3', customer_custom_field_id:3} these all are used to create my textboxes on the front end. Basically just a key value pair. Am I going out this the wrong way? Thank you @MaximBalaganskiy
    Jameson Strocsher
    @jamesond

    This seems to have done the trick for validating dynamic fields and rules.

     this.customRequireds.map((field, index) => {
                        this.rules = [];
                        if (field.required) {
                            field.value = "";
                            this.rules.push(ValidationRules.ensure(field => (<any>field).value).displayName(field.field_name).required().rules[0]);
                            this.controller.addObject(field, this.rules);
    
                        }
                    });
    
     <template repeat.for="field of customFields" if.bind="customFields.length > 0">
                            <div class="form-group">
                                <div class="controls row">
                                    <div class="col-md-4">
                                        <label if.bind="allowOrders" for="custom_${field.customer_custom_field_id}">${field.field_name}<span class="textError" show.bind="field.required">*</span>:</label>
                                        <label if.bind="!allowOrders" for="custom_${field.customer_custom_field_id}">${field.field_name}<span class="textError" show.bind="field.requiredApproval">*</span>:</label>
                                        <input type="text" class="form-control" value.bind="field.value & validate:controller" id="custom_${field.customer_custom_field_id}" name="custom_${field.customer_custom_field_id}">
                                    </div>
                                </div>
                            </div>
    
    
                        </template>

    Please let me know if there is a better way or approach on this. Thank you.

    jbockle
    @jbockle
    aurelia-json-schema-form 1.0 released! checkout https://github.com/jbockle/aurelia-json-schema-form
    andrefcferreira
    @andrefcferreira
    Good Hello Everyone
    Is there anyone that can help me out with noView Models?

    When i click to logout, i send my route to the module (logout.js), he gets there and it will execute with no problem all the commands. it does even logout and destroys all the data (Which is good).

    import { noView } from 'aurelia-framework';
    import authService from 'services/authService';
    import uiService from 'services/uiService';
    
    @noView()
    export class LogoutPage {
      activate() {
        // uiService.impersonate(null, false);
        // authService.logout();
      }
    }

    But there is an error which have been bothering me:

    ERROR [app-router] TypeError: "this.view is null" <
    automatewebpack-internal:///./node_modules/aurelia-templating/dist/native-modules/aurelia-templating.js:3718:5readywebpack-internal:///./node_modules/aurelia-templating-router/dist/native-modules/router-view.js:168:7swapwebpack-internal:///./node_modules/aurelia-templating-router/dist/native-modules/router-view.js:197:12_commitChangeswebpack-internal:///./node_modules/aurelia-router/dist/native-modules/aurelia-router.js:285:16_commitChangeswebpack-internal:///./node_modules/aurelia-router/dist/native-modules/aurelia-router.js:284:7tryCatcherwebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:4954:16_settlePromiseFromHandlerwebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3095:13_settlePromisewebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3152:13_settlePromise0webpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3197:5_settlePromiseswebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3277:13_fulfillwebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3221:13_resolvewebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3487:5_promiseFulfilledwebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3505:9_settlePromisewebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3157:17_settlePromise0webpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3197:5_settlePromiseswebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:3277:13_drainQueueStepwebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:190:9_drainQueuewebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:183:9_drainQueueswebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:199:5drainQueueswebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:69:9owebpack-internal:///./node_modules/bluebird/js/browser/bluebird.js:4208:17 aurelia-logging-console.js:47
    error
    aurelia-logging-console.js:47
    logFactory/<
    aurelia-logging.js:38
    processResult
    aurelia-router.js:1869
    _dequeueInstruction/</<
    aurelia-router.js:1821
    tryCatcher
    bluebird.js:5276
    [22]</module.exports/Promise.prototype._settlePromiseFromHandler
    bluebird.js:3297
    [22]</module.exports/Promise.prototype._settlePromise
    bluebird.js:3354
    [22]</module.exports/Promise.prototype._settlePromise0
    bluebird.js:3399
    [22]</module.exports/Promise.prototype._settlePromises
    bluebird.js:3479
    [22]</module.exports/Promise.prototype._fulfill
    bluebird.js:3423
    [22]</module.exports/Promise.prototype._settlePromise
    bluebird.js:3367
    [22]</module.exports/Promise.prototype._settlePromise0
    bluebird.js:3399
    [22]</module.exports/Promise.prototype._settlePromises
    bluebird.js:3479
    [22]</module.exports/Promise.prototype._fulfill
    bluebird.js:3423
    [22]</module.exports/Promise.prototype._resolveCallback
    bluebird.js:3239
    [22]</module.exports/Promise.prototype._settlePromiseFromHandler
    bluebird.js:3309
    [22]</module.exports/Promise.prototype._settlePromise
    bluebird.js:3354
    [22]</module.exports/Promise.prototype._settlePromise0
    bluebird.js:3399
    [22]</module.exports/Promise.prototype._settlePromises
    bluebird.js:3475
    _drainQueueStep
    bluebird.js:190
    _drainQueue
    bluebird.js:183
    [2]</Async.prototype._drainQueues
    bluebird.js:199
    Async/this.drainQueues
    bluebird.js:69
    schedule/o<
    bluebird.js:4530
    <

    andrefcferreira
    @andrefcferreira
    When i search for the This.view on my project, only 2 files have that reference (if-permission.js and if-user-role.js).
    They are responsible to bind and unbind the active view module, i believe!
    if-permission.js
    import { inject, customAttribute, templateController, BoundViewFactory, ViewSlot } from 'aurelia-framework';
    import userService from 'services/api/userService';
    
    @customAttribute('if-permission')
    @inject(BoundViewFactory, ViewSlot)
    @templateController
    export class IfPermission {
    
      constructor(viewFactory, viewSlot) {
    
        this.viewFactory = viewFactory;
        this.viewSlot = viewSlot;
        this.showing = false;
        this.view = null;
        this.bindingContext = null;
        this.overrideContext = null;
      }
    
      /**
      * Binds the if to the binding context and override context
      * @param bindingContext The binding context
      * @param overrideContext An override context for binding.
      */
      bind(bindingContext, overrideContext) {
        // Store parent bindingContext, so we can pass it down
        this.bindingContext = bindingContext;
        this.overrideContext = overrideContext;
        this.valueChanged(this.value);
      }
    
      valueChanged(newValue) {
        if (this.__queuedChanges) {
          this.__queuedChanges.push(newValue);
          return;
        }
    
        let maybePromise = this._runValueChanged(newValue);
        if (maybePromise instanceof Promise) {
          let queuedChanges = this.__queuedChanges = [];
    
          let runQueuedChanges = () => {
            if (!queuedChanges.length) {
              this.__queuedChanges = undefined;
              return;
            }
    
            let nextPromise = this._runValueChanged(queuedChanges.shift()) || Promise.resolve();
            nextPromise.then(runQueuedChanges);
          };
    
          maybePromise.then(runQueuedChanges);
        }
      }
    
      _runValueChanged(newValue) {
        newValue = userService.hasPermission(newValue);
        if (!newValue) {
          let viewOrPromise;
          if (this.view !== null && this.showing) {
            viewOrPromise = this.viewSlot.remove(this.view);
            if (viewOrPromise instanceof Promise) {
              viewOrPromise.then(() => this.view.unbind());
            } else {
              this.view.unbind();
            }
          }
          this.showing = false;
          return viewOrPromise;
        }
    
        if (this.view === null) {
          this.view = this.viewFactory.create();
        }
    
        if (!this.view.isBound) {
          this.view.bind(this.bindingContext, this.overrideContext);
        }
    
        if (!this.showing) {
          this.showing = true;
          return this.viewSlot.add(this.view);
        }
      }
    
      /**
      * Unbinds the if
      */
      unbind() {
        if (this.view === null) {
          return;
        }
    
        this.view.unbind();
    
        if (!this.viewFactory.isCaching) {
          return;
        }
    
        if (this.showing) {
          this.showing = false;
          this.viewSlot.remove(this.view, true, true);
        }
        this.view.returnToCache();
        this.view = null;
      }
    }
    if-user-role.js
    import { inject, customAttribute, templateController, BoundViewFactory, ViewSlot } from 'aurelia-framework';
    import userService from 'services/api/userService';
    
    @customAttribute('if-user-role')
    @inject(BoundViewFactory, ViewSlot)
    @templateController
    export class IfUserRole {
    
      constructor(viewFactory, viewSlot) {
        this.viewFactory = viewFactory;
        this.viewSlot = viewSlot;
        this.showing = false;
        this.view = null;
        this.bindingContext = null;
        this.overrideContext = null;
      }
    
      /**
      * Binds the if to the binding context and override context
      * @param bindingContext The binding context
      * @param overrideContext An override context for binding.
      */
      bind(bindingContext, overrideContext) {
        // Store parent bindingContext, so we can pass it down
        this.bindingContext = bindingContext;
        this.overrideContext = overrideContext;
        this.valueChanged(this.value);
      }
    
      valueChanged(newValue) {
        if (this.__queuedChanges) {
          this.__queuedChanges.push(newValue);
          return;
        }
    
        let maybePromise = this._runValueChanged(newValue);
        if (maybePromise instanceof Promise) {
          let queuedChanges = this.__queuedChanges = [];
    
          let runQueuedChanges = () => {
            if (!queuedChanges.length) {
              this.__queuedChanges = undefined;
              return;
            }
    
            let nextPromise = this._runValueChanged(queuedChanges.shift()) || Promise.resolve();
            nextPromise.then(runQueuedChanges);
          };
    
          maybePromise.then(runQueuedChanges);
        }
      }
    
      _runValueChanged(newValue) {
        newValue = userService.hasRole(newValue);
    
        if (!newValue) {
          let viewOrPromise;
          if (this.view !== null && this.showing) {
            viewOrPromise = this.viewSlot.remove(this.view);
            if (viewOrPromise instanceof Promise) {
              viewOrPromise.then(() => this.view.unbind());
            } else {
              this.view.unbind();
            }
          }
    
          this.showing = false;
          return viewOrPromise;
        }
    
        if (this.view === null) {
          this.view = this.viewFactory.create();
        }
    
        if (!this.view.isBound) {
          this.view.bind(this.bindingContext, this.overrideContext);
        }
    
        if (!this.showing) {
          this.showing = true;
          return this.viewSlot.add(this.view);
        }
      }
    
      /**
      * Unbinds the if
      */
      unbind() {
        if (this.view === null) {
          return;
        }
    
        this.view.unbind();
        if (!this.viewFactory.isCaching) {
          return;
        }
    
        if (this.showing) {
          this.showing = false;
          this.viewSlot.remove(this.view, true, true);
        }
        this.view.returnToCache();
        this.view = null;
      }
    }
    I have been debugging but reached no conclusion... all logs that i try to check this.view they are not null...
    andrefcferreira
    @andrefcferreira
    Oh! This is a result of an old aurelia framework version and i am at the end of the aurelia upgrade. Which this is the only error that i have been getting
    andrefcferreira
    @andrefcferreira
    Good Hello Everyone
    andrefcferreira
    @andrefcferreira
    Here is a stackoverflow for my problem
    Arne Deruwe
    @arnederuwe
    @andrefcferreira the main discussion room for Aurelia is here: https://gitter.im/aurelia/Discuss
    you should post all non-validation related things there
    andrefcferreira
    @andrefcferreira
    What do you understand as Validation then?
    Okay! My question is: what is the porpuse of the group then?
    Arne Deruwe
    @arnederuwe
    this is the room discussing issues with the Aurelia validation plugin: https://github.com/aurelia/validation
    Charles Lindsay
    @VagyokC4
    image.png
    I'm experiencing an issue where my validation controller is missing the html element required to show the validation error
    I just recently upgraded to the latest bits and this issue showed up
    Any ideas on how to get the element to re-register?
    Ischca
    @Ischca
    Is there a way to signal an error to validation-errors when you call controller.validate ({object: this.obj})?
    Ischca
    @Ischca
    this is solved
    jsprpalm
    @jsprpalm

    Hi. I tried to simplify the html needed to create a form with fields+validation+error display by creating a custom component.

    validated-input.html

    <template>
        <div class="form-input ${class}">
            <slot name="icon"></slot>
            <label if.bind="!floatingLabel">${label}</label>
            <div>
                <div class="ui input primary-input">
                    <input type="text" ref="field" class="${errors.length > 0 ? 'has-errors': ''}"
                        keydown.delegate="keyDownHandler($event)" value.bind="value" blur.trigger="blur()" input.trigger="input()" autocomplete="off">
                    <div if.bind="floatingLabel" class="floating-label"><span class="floating-label-focus">${label}</span></div>
                </div>
                <div if.bind="errors.length > 0" class="validation-error">
                    <i class="exclamation triangle icon"></i>
                    <span repeat.for="e of errors">${e.message}</span>
                </div>
            </div>
        </div>
    </template>

    validated-input.ts

    import { ValidationController, ValidateResult, validateTrigger } from "aurelia-validation";
    import { customElement, bindable, containerless, autoinject, bindingMode, DOM } from "aurelia-framework";
    
    @autoinject
    @containerless
    @customElement("validated-input")
    export class ValidatedInput {
        @bindable field: HTMLInputElement;
        @bindable label: string;
        @bindable class: string = "";
        @bindable({ defaultBindingMode: bindingMode.twoWay }) value: string;
        @bindable name: string;
        @bindable floatingLabel: boolean = false;
        @bindable validationTrigger: string = "change";
        @bindable maxlength: string | null = null;
        @bindable pattern: string | null = null;
        errors: ValidateResult[];
        private controller: ValidationController;
    
        constructor(private element: Element) {
        }
    
        bind(bindingContext: any) {
            this.field.setAttribute("value", this.value || "");
            this.controller = bindingContext.controller;
            if (this.maxlength) {
                this.field.setAttribute("maxlength", this.maxlength);
            }
            if (this.pattern) {
                this.field.setAttribute("pattern", this.pattern);
            }
            this.controller.subscribe((e) => this.errors = e.results.filter((x) => x.propertyName === this.name && !x.valid));
        }
    
        blur() {
            if (this.validationTrigger === "blur") {
                this.validate();
            }
        }
    
        input() {
            if (this.validationTrigger === "change") {
                this.validate();
            }
        }
    
        private validate() {
            this.field.setAttribute("value", this.value || "");
            this.controller.validate().then((validate) => {
                this.errors = validate.results.filter((x) => x.propertyName === this.name && !x.valid);
            });
        }
    
        private keyDownHandler(e: KeyboardEvent) {
            if (e.key === "Enter") {
                this.element.dispatchEvent(DOM.createCustomEvent("enter"));
            }
            return true;
        }
    }

    The problem I have is that I need (I think) to have each field subscribe to the validation callback to perform their logic to filter the errors collection. This is because a validation can be triggered by the page that contains the submit button. But by having each field subscribe to the validation callback this also means that as soon as I validate one of the fields in the blur or change handlers all of the fields are validated. I only want this full form validation when you try to submit the form.

    The ValidationController and the ValidationRules are created and defined in the containing page.

    I feel that I have over complicated this solution and that there must be something simpler?

    Antonio
    @eagle06_gitlab