Search code examples
polymerpolymer-1.0paper-elements

Polymer 1.0 input validity observer


I'm having some trouble watching for changes to input validity in polymer 1.0. More precisely, an observer function that should fire on any changes to the bound 'invalid' property is not firing as I'd expect it to. For instance, the function may fire when the control first becomes invalid, but if becomes valid again, the observer function is not being triggered (invalid not becoming false?). In my current example, I happen to be utilizing Polymer 1.0's gold-email-input element as follows:

Extract from my custom element's local DOM template:

<paper-icon-item>
      <iron-icon icon="social:person"></iron-icon>
      <gold-email-input id="userEmail" bind-value="{{userEmail}}" required auto-validate invalid="{{invalidEmail}}" error-message="Invalid email address"></gold-email-input>
</paper-icon-item>

Extract from my custom element's script declaration:

properties: {
      invalidEmail: {type: Boolean, observer: 'emailValidityChanged'}
}

emailValidityChanged: function(newVal, oldVal) {
      console.log(this.nodeName + " emailValidityChanged observer fired\n"); 
}

I'm probably missing something straightforward here? I've also tried observing changes on the userEmail property, and then checking the state of this.$.userEmail.invalid within the observer function, to no avail. It does appear that the invalid property is not being reset when the entry becomes valid. Any suggestions? Maybe another approach altogether?


Solution

  • I think it might be a bug - I've created a new issue to seek clarification with the project owners on expected behavior. Currently, it seems that invalid is set up as a one-way bind from host to child, but I thought it shouldn't be. I can get your snippet working by making changes to paper-input-behavior, paper-input-container and gold-email-input, but until the project owners clarify on what invalid is really used for, don't.

    As a workaround, use MutationObservers instead.

    <template>
        My Email: <span>{{myEmail}}</span><br>
        Validity: <span>{{validity}}</span><br>
        <gold-email-input id="foo" bind-value="{{myEmail}}" required
                          auto-validate error-message="Invalid email address">
        </gold-email-input>
    </template>
    
    <script>
        ...
          attached: function () {
            var t = this;
            var observer = new MutationObserver(function (mutations) {
              mutations.forEach(function (mutation) {
                if (mutation.target.classList.contains("is-invalid")) {
                  // stuff to do when email is invalid
                  t.validity = "No, email is invalid";
    
                } else {
                  // stuff to do when email is valid
                  t.validity = "Yes, email is valid";
    
                }
              });
            });
            var node = this.$.foo.$.container.$$(".add-on-content");
            observer.observe(node, {
              attributes: true,
              attributeFilter: ["class"]
            });
          }
        ...
    </script>
    

    Working Jsbin: http://jsbin.com/resokidako/edit?html,output

    Update 1

    Observe the add-on-content node instead.

    Updated Jsbin: http://jsbin.com/wivimovufi/1/edit?html,output