Skip to content
This repository has been archived by the owner on Sep 7, 2022. It is now read-only.

Observing input validity - what is invalid property used for? #26

Closed
zerodevx opened this issue Jul 28, 2015 · 9 comments
Closed

Observing input validity - what is invalid property used for? #26

zerodevx opened this issue Jul 28, 2015 · 9 comments

Comments

@zerodevx
Copy link
Contributor

I took interest in this SO question: http://stackoverflow.com/questions/31643650/polymer-1-0-input-validity-observer and I can certainly imagine use-cases to observe input validity.

Given that I have a template

<gold-email-input id="foo" bind-value="{{myEmail}}" auto-validate
                  error-message="Invalid email address" invalid="{{isInvalid}}">
</gold-email-input>

and prototype

properties: {
  myEmail: String,
  isInvalid: {
    type: Boolean,
    observer: "isInvalidChanged"
  }
}

gold-email-input extends Polymer.PaperInputBehavior, and according to this,

/**
* Returns true if the value is invalid. Bind this to both the <paper-input-container>'s
* and the input's invalid property.
*/
invalid: {
type: Boolean,
value: false
},

the invalid property returns true if the value is invalid. In this case, is there a reason why notify: true is not set?

Similarly, gold-email-input uses paper-input-container and it is not set to notify upwards as well.

Lastly, in gold-email-input.html, the invalid attribute is set to a one-way bind from host to paper-input-container.

If I make the above 3 changes, the invalid property becomes observable. Is this a bug?

@Sinjins
Copy link

Sinjins commented Jul 28, 2015

+1

2 similar comments
@MWalid
Copy link

MWalid commented Aug 8, 2015

+1

@PaulHMason
Copy link

+1

@notwaldorf
Copy link
Contributor

@zerodevx invalid is used by the PaperInputContainer to mark itself as invalid (and display the red underline and error message). The reason why it isn't observable is that nobody has needed it before (a paper-input or a gold-email-input will mark itself as invalid, and pass that value down to its paper-input-container, which will actually use it for something)

Out of curiosity, what is your use case for making invalid a notify property (i.e. having someone listen to changes in the gold-email-input's validity)?

@Sinjins
Copy link

Sinjins commented Aug 17, 2015

@notwaldorf @zerodevx I authored the original SO post noted above. My use case was as follows:

I have an element that acts as the container for a number of polymer elements used to collect and validate various user profile data (including user's email). This element is used in the app for both user registration and user profile editing, for example. Therefore, this common element is implemented by other custom/parent elements for the purposes of registration or profile editing. How each of these parent elements handle validity differs, so I need to be able to fire a custom event for the host element to uniquely act upon (i.e. implement a validity handler) whenever the validity of any of these fields change. It is helpful, for these instances, to be able to observe the validity of the entries in order to then fire the custom event for the host/parent to act upon as desired.

I hope I've explained this effectively, as I'm just providing these details quickly from somewhat distant memory.

zerodevx added a commit to zerodevx/gold-email-input that referenced this issue Aug 21, 2015
@zerodevx
Copy link
Contributor Author

Hi @notwaldorf - thanks for your attention; been meaning to ask... who's waldorf?? Anyhow,

Observing input validity

I'm quite sure there are valid use-cases for this - there's been a few +1s to this, and I think others would like to have this option as well. Say I want to pre-populate the field imperatively, and want to be notified when an error is triggered so that I can take some actions. Setting invalid to notify: true looks like a simple way to get this information.

However, if the Polymer owners choose to provide this functionality, it makes more sense to instead fire a paper-input-validity-changed custom event from paper-input-container, since this is the base element in use by all other custom input web components. As the event bubbles up, developers can easily and declaratively listen for that from their respective component.

Regarding my SO answer

My original answer uses MutationObservers API to capture validity change as a workaround - it is on hindsight an anti-pattern - partly because MOs are unable to pierce through the shadow dom under native behavior.

If I understand your intentions correctly, perhaps the recommended pattern is to manually perform validation - eg.

<template>
  ...
  <gold-email-input id="foo" value="{{email}}" error-message="Invalid email!!"></gold-email-input>
</template>
<script>
  ...
  properties: {
    email: { type: String, observer: "emailChanged" }
  },
  emailChanged: function () {
    var valid = this.$.foo.validate();
    if (!valid) {
      // do my thing
    }
  }
</script>

Issue when setting value imperatively

Which brings me to the next issue - setting value imperatively does not trigger a validation when auto-validate is asserted. Here is the repro: http://jsbin.com/nicubapaya/edit?html,output

The problem lies between L120 - L132 - it is more generic to listen to value changes instead of keypresses.

Issue deleting email value when required is negated

If the input is not required, expected behavior should be when value = "", the email should be considered "valid". Referring to the above repro, try typing something, then deleting it - the input remains in "invalid" status.

The problem lies in L136 - L138 - the validate() method returns true without actually setting paper-input-container's invalid property.

Putting it all together

Here is the PR. This fixes:

  1. Auto-validating of values that are set imperatively;
  2. ensuring correct behavior when auto-validate is true and required is false;
  3. and save some CPU cycles by first checking if change is needed before actually changing.

I have omitted setting invalid to notify upwards for now (the irony is not lost on me) - perhaps the pattern mentioned above is the recommended solution.

Thanks,
J

@zerodevx
Copy link
Contributor Author

@notwaldorf - I see you observed value instead of keypresses in your latest commits - so this fixes the first issue stated in my previous comment.

I will rebase, create a new issue, and re-submit a PR to fix the second.

As for observing input validity, please confirm for the community's benefit that

<template>
  ...
  <gold-email-input id="foo" value="{{email}}" error-message="Invalid email!!"></gold-email-input>
</template>
<script>
  ...
  properties: {
    email: { type: String, observer: "emailChanged" }
  },
  emailChanged: function () {
    var valid = this.$.foo.validate();
    if (!valid) {
      // do my thing
    }
  }
</script>

is the recommended pattern - then this thread can be finally closed.

Thanks,
J

@notwaldorf
Copy link
Contributor

@zerodevx I think that looks fine. I don't actually have an objection to making invalid (in PaperInputBehaviour) a notify property. Also, that might save you a call to validate.

Created: PolymerElements/paper-input#159

@notwaldorf
Copy link
Contributor

Closing this, as I think we're all sorted!

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