knownasilya / ember-toggle

Checkbox based Toggle Switches for Ember
http://knownasilya.github.io/ember-toggle/
MIT License
112 stars 52 forks source link

`x-toggle` toggles on click when the `onToggle` action does not update the value #91

Closed lolmaus closed 7 years ago

lolmaus commented 7 years ago

How to reproduce

{
  value: false,

  actions: {
    toggle () {}
  }
}
<p>value: {{value}}</p>

{{x-toggle value=value onToggle=(action 'toggle')}}

image

Now click the toggle.

What I expect to happen

The component should not toggle because the action does not update the value.

What actually happens

image

The component does toggle, the value and the component's state are out of sync.

Reproduction

https://ember-twiddle.com/85bcda587638b642fcf254d550488899?numColumns=2&openFiles=controllers.application.js%2Ctemplates.application.hbs

Notes

Happens only for clicking. Dragging works correctly: the component toggles only when the action updates the value.

lolmaus commented 7 years ago

I've just tried one-way-checkbox from ember-one-way-controls and it has the same problem. :sob:

https://ember-twiddle.com/3ce9e7f1dd2a09ae7c9219a8031e69be?numColumns=2&openFiles=controllers.application.js%2Ctemplates.application.hbs

lolmaus commented 7 years ago

Related:

scottkidder commented 7 years ago

Just ran into this as well.

webark commented 7 years ago

are you sure this is a bug? If you did a standard checkbox input, and set up a one way binding with it, the check box would trigger but if you didn't update the value, it wouldn't update.. having it not update, you'd have resetup two way binding. Right?

lolmaus commented 7 years ago

@webark, the <input> element is a remnant of 20th century when the only way to communicate with the backend was to submit a form. At that time, nobody thought about DDAU. Two-way binding was the only way. Actually, there was no binding at all, because there was no other property to bind to. In other words, the internal checked property of the <input> element was the only source of truth.

With Ember, the primary source of truth is a property that you pass as value. The <input>'s checked property must always be in sync with it.

Also, ember-toggle tries to follow DDAU strictly. The value is bound to the <input>. But this binding is one-way: since v3 (I think), it is no longer capable of mutating the value. All it can do is to report back to the app: "the user has flicked the toggle to <boolean>".

If the app decides not to change value in response to this user action, yet the <input>'s state has changed, then the app's internal state has become inconsistent. This should never happen.

@knownasilya Are we on the same page?

scottkidder commented 7 years ago

I think I have a failing test for this in #94