简体   繁体   中英

Checkbox binding of checked state inverted in Chrome

I'm using Ember v2.5.1 and Ember data v2.6.2 and I have a series of nested components to render a hierarchical tree of categories. There is a closure action in the lowest level component categories-tree-node , which calls the toggleAddCategory function in the actions of the categories-select component and passes up the relevant category object.

It works as expected in Safari, but for some reason the checked state is passed through inverted in Chrome and FF. The strange thing is that the checked state binding of the value itself renders correctly elsewhere in the template when the checkboxes are changed.

I have created a demo here , if you try checking/unchecking the boxes in Chrome/FF vs Safari you should see the issue. Is there a prefered way of handling this type of action binding with checkbox checked states? I have read that using Observers is considered an anti-pattern in Ember 2 and above, also when I tried this it did not work for the child categories.

Ok so your twiddle shows that the state is unchanged in Chrome but changed in Safari.

This is most likely a bug with jQuery in Safari because Ember.CheckBox sets checked using the jQuery prop method:

change() {
  set(this, 'checked', this.$().prop('checked'));
}

A workaround solution would be to use the checkbox as an angle-bracket component ( which have one-way bindings by default ) to ensure the checked binding is not changed by the input component and instead use the passed in closure action to manually toggle the checked state yourself.

This also goes along with the Ember recommended best practice for setting parent properties from components using the Data Down - Actions Up pattern.

Note: You might want to use the onchange event rather than onclick .

Child components/categories-tree-node.hbs

<input type="checkbox"
       checked={{category.checked}} <!-- checked is just passed from above, not set within the component -->
       onchange={{action toggle category}} <!-- onchange calls the passed in action which toggles checked -->
       id={{concat elementId '-' category.slug}}
>

...

Parent components/categories-select.js

export default Ember.Component.extend({
  // ...

  actions: {

    toggleAddCategory(category) {
      category.toggleProperty('checked'); // toggle the property yourself

      // ...  
    }

  }
});

If your parent action only does the toggle and nothing else, you probably don't need it and can do the toggling right inside the components/categories-tree-node.hbs using the mut helper:

<input type="checkbox"
       checked={{category.checked}} <!-- checked is just passed from above, not set within the component -->
       onchange={{action (mut category.checked) value="target.checked"}} <!-- onchange automatically sets category.checked -->
       id={{concat elementId '-' category.slug}}
>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM