New class bindings discard other classes when they update


#1

Starting with Ember 1.10, if I am binding a class to an element and then later add a class to that element (through direct DOM manipulation using jQuery in this case), that class will be discarded when the bound value changes. Prior to 1.10 these classes were left alone.

I know I shouldn’t be messing around with jQuery, that I should be using the tools that Ember provides instead. One of the first things I did when I joined my project was work towards removing jQuery code. However, we have a pattern library that we are required to use in all of our apps. This library is generally platform agnostic, and our apps are not all Ember. Included in the library are dropdowns, and they come with a little script to make the dropdowns work properly. This script sets classes on the dropdowns, its part of how it works. We need to use Ember for the dropdowns too, because they need to change depending on the state of the app.

I would prefer if with the new HTMLbars stuff (which I am really looking forward to using) would preserve classes that are not being updated through a property change. I understand that things are happening in a whole new way, and this might not be possible. But if it is, I think we should do that.

Here is a jsbin illustrating what is happening. If you turn the text red, and then add a border, the text stays red. But then when you toggle the text color again, the border disappears because the class has been removed.

This is my first real dive into the Ember source code, and I would appreciate it if someone could point me to the code that actually updates the classes on the element when a bound property changes? I’m having trouble finding it.


#2

I can’t help you in your deep dive but I did notice one interesting thing that you may not have tried yet.

If you add the border class like this

<p class="border {{if isRed 'red'}}">
  Toggling a class directly on the element will not affect the class that is toggled through the Ember binding.
</p>

the toggle works.

If you put the classes you need in the template first and then turn them off on didInsertElement your jquery stuff should work.


#3

Thanks varblob, but when I do that, then it always adds the class whenever the binding is refreshed. Try it here, click the button at the bottom to remove the border, then click the button at the top to change the color and you will see the border is added back automatically.

This is what it looks like when I add the border class in the template, and remove it on didInsertElement, it has the same problem.


#4

Yup I’m idiot. Upon further thought it makes sense it doesn’t work because on any change it will rerender the template which has a hard coded value of border in it… Doh!


#5

I found the code, here is the PR to fix this issue: https://github.com/emberjs/ember.js/issues/10856

For the record, here is the issue I made: https://github.com/emberjs/ember.js/pull/10857