Skip to content
This repository has been archived by the owner on May 15, 2023. It is now read-only.

Using Polymer 2.0 class based element definition doesn't register validator element #30

Closed
juriejan opened this issue Apr 19, 2017 · 8 comments

Comments

@juriejan
Copy link

juriejan commented Apr 19, 2017

Description

When using the Polymer 2.0 class based element definition for defining a validator element the validator isn't registered properly as the is property is undefined due to the property being declared as a static class property which isn't defined at this, which at the time of reference refers to an instance rather than the class definition.

Example

https://gist.github.com/juriejan/b6bcb4cbf816d84fb2aeea0a0fc0dd1d

@aaronanderson
Copy link

I am not sure if my issue is related but in the 2.0 version of iron-validator-behavior/iron-validator-behavior.html the validatorName property from 1.0 is removed and the Polymer.IronMeta key is not configurable. This ends up limiting the referenceable instances of a validator element to one. To work around this issue I included a second invocation of Polymer.IronMeta in the custom validator but I think mapping a unique key should be handled in the behavior like it was in 1.0.

Example of Workaround

https://gist.github.com/aaronanderson/c46f18d0ab30f1ba16f561351adb7ff7

@juriejan
Copy link
Author

juriejan commented May 9, 2017

@aaronanderson our issues are definitely part of the same discussion. We need to consider whether we'd like to define a new element for each variation on a validator (which seems like where it's headed with the 2.0 implementation) or if we'd like to have the option of defining validators separately from elements and allow customisation.

For example, it would seems a bit extreme for me to have to define a new element just for a validator that needs to check for a different minimum and maximum length of a value.

This makes me lean more toward allowing the definition of validator separate from element (using a validator name property). We can then also fallback to using the element name if the validator name is not provided, but I would not encourage this as there would be a high probability of having more than one validator with the same name in the global validator namespace and it might cause confusion for users viewing examples of usage.

I'll submit a pull request a little later that reintroduces just the validator name and doesn't fall back to the element name.

@akc42
Copy link

akc42 commented Jun 1, 2017

Anything happening with this?

Not sure with the work around. I just did the following

    class PasProfilePasswordValidator extends Polymer.Element {
      static get is() {return 'pas-profile-password-validator';}
...
      ready() {
        super.ready();
        new Polymer.IronMeta({type: 'validator', key: PasProfilePasswordValidator.is, value: this});
      }

Thats all the behavior does anyway

@juriejan
Copy link
Author

I've created a very simple PR for this just to bring more attention to the problem. I'll hopefully find time to implement a class based behaviour mixin for this, which I feel is the real forward thinking solution.

@ghost
Copy link

ghost commented Jun 23, 2017

Am I the only one to not be able to use this kind of validation on a Polymer 2 application?
I tried this:

<dom-module id="ey-generic-validator">
    <template>
        <style>
        </style>
    </template>
    <script>
        class EyGenericValidator extends Polymer.mixinBehaviors([Polymer.IronValidatorBehavior], Polymer.Element) {
            static get is() { return 'ey-generic-validator'; }
        }
        customElements.define(EyGenericValidator.is, EyGenericValidator);
    </script>
</dom-module>

With the mixinBehaviors syntax because of the 'old style' IronValidatorBehavior.
And using it like in:

<ey-generic-validator id="clientGisValidator" name="clientGisValidator" validator-name="clientGisValidator"></ey-generic-validator>
                                    <iron-input id="clientGis" class="fullwidth" value="{{clientGis::input}}" auto-validate validator="clientGisValidator">
                                        <input class="fullwidth" validator="clientGisValidator">
                                    </iron-input>

I tried every kind of attribute, to link the name, but without any luck.
When I step through the source code, this method always return undefined:

get _validator() {
      debugger;
      return Polymer.IronValidatableBehaviorMeta &&
          Polymer.IronValidatableBehaviorMeta.byKey(this.validator);
    },

What am I missing? I'm getting crazy... :-)
Andrea

@akc42
Copy link

akc42 commented Jun 26, 2017

@andreabioli The problem, if I remember it correctly, is that IronValidatorBehavior tries the get the name of the current instance using this.is. In Polymer2 that doesn't work

My workaround above just strips away all the extras around adding a simple validator key value pair to the iron-meta global stuff needed to register the element as a validator that can be used in the get_validator() call you reference above

@hyyan
Copy link

hyyan commented Jul 23, 2017

@andreabioli , @akc42 , @juriejan this.is In Polymer2 doesn't work because is is a static method .
Static methods are not directly accessible using the this keyword from non-static methods. You need to call them using the class name: CLASSNAME.STATIC_METHOD_NAME() or by calling the method as a property of the constructor,

that is why something like the following will work

class PasProfilePasswordValidator extends Polymer.Element {
      static get is() {return 'pas-profile-password-validator';}
...
      ready() {
        super.ready();
        new Polymer.IronMeta({type: 'validator', key: PasProfilePasswordValidator.is, value: this});
      }

a better solution would be to replace PasProfilePasswordValidator.is with this.constructor.is

@BAGELreflex
Copy link

BAGELreflex commented Sep 3, 2018

This was closed as fixed, however it does not really seem to fix the issue of targeting a validator that takes conditional arguments.

Take, for example:

<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/iron-validator-behavior/iron-validator-behavior.html">
<dom-module id="password-validator">
    <script>
        /**
         * @customElement
         * @polymer
         */
        class PasswordValidator extends Polymer.mixinBehaviors([Polymer.IronValidatorBehavior], Polymer.Element)
        {
            static get is() { return 'password-validator'; }

            static get properties() {
                return {
                  name: String
                  , comparator: String
                };
            }

            validate(value) {
                if (typeof comparator !== "undefined") {
                 return value === comparator;
                }
                return this._checkStrength(password);
            }

            _checkStrength(password)
            {
              // Password strength check logic
            }
        }

        window.customElements.define(PasswordValidator.is, PasswordValidator);
    </script>
</dom-module>
<password-validator name="pw_validator"></password-validator>
<password-validator name="pw_again_validator" comparator="[[newPassword]]"></password-validator>
<paper-input type="password" label="New Password" validator="pw_validator" error-message="Invalid password" auto-validate>
<paper-input type="password" label="New Password Again" validator="pw_again_validator" error-message="Passwords do not match" auto-validate>

In order to make something like this work, using the suggested fix in this thread (which has been committed into master) only works if the validator attribute is being targeted by the actual element name, such as:

<password-validator></password-validator>
<paper-input type="password" validator="password-validator"></paper-input>

As outlined in this StackOverflow post, the following can be used to target by name or id attributes:

connectedCallback()
{
    super.connectedCallback();
    
    var validatorName = PasswordValidator.is;
    
    if (this.name)
    {
        validatorName = this.name;
    }
    
    new Polymer.IronMeta({ type: 'validator', key: validatorName, value: this });
 }

With the above in your Validator class, referencing by name will work:

<password-validator name="pw_validator"></password-validator>
<password-validator name="pw_again_validator" comparator="[[newPassword]]"></password-validator>
<paper-input type="password" label="New Password" validator="pw_validator" error-message="Invalid password" auto-validate>
<paper-input type="password" label="New Password Again" validator="pw_again_validator" error-message="Passwords do not match" auto-validate>

The above issue was briefed earlier in this post.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants