Search code examples
polymerpaper-elements

Control a paper-checkbox's state


I'm trying to setup an element with a paper-checkbox inside of it. I want the checkbox's checked state to be controlled by the response of an ajax call.

HTML:

<epic-list-episode checked="<%= episode.seen? %>">
  <p><strong><%= episode.show.name %></strong></p>
</epic-list-episode>

Custom element:

<polymer-element name="epic-list-episode" attributes="checked">

  <template>
    <link rel="stylesheet" href="epic-list-episode.css.scss" />
    <div horizontal layout center>
      <div flex>
        <content></content>
      </div>
      <div vertical layout>
        <paper-checkbox checked?="{{checked === 'true'}}" on-change="{{changeHandler}}"></paper-checkbox>
      </div>
    </div>
  </template>

  <script>
    Polymer({
      changeHandler: function(event) {
        //Send ajax, wait for error/success callback
        //checkbox.checked = response from ajax
      }
    });
  </script>

</polymer-element>

How can this be achieved? I've tried return false but the checkbox still does its toggle animation.

To clarify, here is the flow i want:

  1. Checkbox is unchecked
  2. I click the checkbox (I don't want it to toggle yet)
  3. Ajax request is sent off
  4. Wait for the callback
  5. If it's successful, toggle the state of the checkbox

Solution

  • I don't think you need that checked attribute at all.

    What you can do is, when the on-change is called, set the checked property of the paper-checkbox back to its previous value. And then after the ajax callback, set it back to what it should be.

    changeHandler: function (event, detail, sender) {
        this.$.checkbox.checked = !this.$.checkbox.checked;
    
        // give the checkbox a little loading animation
        var loading = new CoreAnimation();
        loading.duration = 750;
        loading.easing = 'ease-in';
        loading.keyframes = [{ opacity: 1, transform: "scale(1)" }, { opacity: 0.4, transform: "scale(0.9)" }];
        loading.direction = 'alternate';
        loading.iterations = '1000';
        loading.target = this.$.checkbox;
        loading.play();
    
        // give it a little delay to act like a callback
        this.job('delay', function () {
            // stop the animation
            loading.finish();
    
            this.$.checkbox.checked = !this.$.checkbox.checked;
        }, 3000);
    }
    

    Note that I have also included some animation code to make the user feel like the paper-checkbox is doing something, for a better user experience. Please see this jsbin for a working example.