Skip to content

on-change doesn't get triggered when change happens programmatically #484

Description

@mohsen1

I've this my very first web components called grouped-checkbox. Everything works great when I click on checkboxes and change their value. But when I change checked status of checkboxes programmatically, my change listener is not being triggered.

I've created this bin to demonstrate the issue:
http://jsbin.com/dixewowa/1/edit

I've my change listener on the wrapper div to use one listener for all checkboxes.
Maybe this is the issue?

  <template>
    <style>
      #group > * {
        display: block;
        margin-left: 1em;
      }
    </style>

    <label>
      <input type="checkbox" id="all" on-change="{{allChangeListener}}">
      {{label}}
    </label>
    <div id="group" on-change="{{groupChangeListener}}">
      <content></content>
    </div>
  </template>

Activity

  1. dfreedm commented on Apr 28, 2014

    @dfreedm
    Member

    This is unfortunately how a checkbox works, the change event is only fired if an event triggered the change, not if checked is toggled.

    Example jsbin without polymer: http://jsbin.com/bebevoyo/1/edit

  2. mohsen1 commented on Apr 28, 2014

    @mohsen1
    Author

    Thanks for the feedback @azakus
    Do you have any recommendation for observing checked the Polymer way? Should I use Object.observe?

  3. dfreedm commented on Apr 28, 2014

    @dfreedm
    Member

    No, Object.observe does not observe native properties of DOM elements (they are magical things).

    Instead, you can do one of two things:

    1. Bind all the checkbox checked values into the model and only touch the model
    2. Wrap checkboxes in another element, bind the native checkbox checked to your wrapper element, and then only touch the wrapper element's checked property.

    Example 1:

    <template id="t" bind>
      <input type="checkbox" id="one" value="{{checkboxOneValue}}">
    </template>
    <script>
      t.model = {checkboxOneValue: false};
      // change
      t.model.checkboxOneValue = true;
    </script>

    Example 2:

    <polymer-element name="my-checkbox" attributes="checked">
      <template>
        <input type="checkbox" checked="{{checked}}">
      </template>
      <script>
        Polymer('my-checkbox', {
          checked: false
        });
      </script>
    </polymer-element>
    
    <my-checkbox checked="true"></my-checkbox>

    We used #2 for Polymer by making core-input, but both are valid uses of the databinding implementation in Polymer.

  4. sjmiles commented on Apr 28, 2014

    @sjmiles
    Contributor

    A couple of other options are:

    1. Provide a method that scans the checkboxes for changes manually, and require that users who mess with checkbox state in code call this method. This is what the checkbox API design wants users to do (for better or worse): if you mess with checkboxes programatically, you must manage those changes programatically.
    2. Re-imagine your grouped-checkbox as a higher-level system that consumes something closer to the raw option data (via attributes, javascript, or DOM) and renders labels and checkboxes itself. Then you can provide an API for manipulating the states yourself and have a greater degree of control.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions