Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Remove support for nested objects/arrays in ng-class #15960

Closed
jbedard opened this issue May 3, 2017 · 4 comments
Closed

Remove support for nested objects/arrays in ng-class #15960

jbedard opened this issue May 3, 2017 · 4 comments

Comments

@jbedard
Copy link
Collaborator

jbedard commented May 3, 2017

189461f caused an issue with nested literal objects/arrays in ng-class (#15905), essentially because it allowed the expression inputs (a watch optimization) to be used properly in the case of literals with interceptorFns.

Instead of reverting 189461f, or changing ng-class to use deep watch, or declaring its interceptor as $stateful - I'd like to drop nested object/array support from ng-class. This will align ng-class with the Angular version, should improve performance, should simplify the ng-class code a bit.

This would be a breaking change in 1.7.

Any strong objections? Strong use cases for nested objects/arrays in ng-class?

@lgalfaso
Copy link
Contributor

lgalfaso commented May 3, 2017

Putting a side the specific way that this should be resolved, there are a few points that should be covered:

  1. Even when nested arrays/objects are no longer supported, simple objects/arrays are supported

  2. 189461f caused
    ng-class="[root.obj1, root.obj2]"
    and
    $scope.root.styles2 = [root.obj1, root.obj2];
    ng-class="root.styles2"
    to behave differently. This discrepancy must be avoided

  3. Even if nested arrays/objects are not supported, then, if someone creates a stateless filter that expose the nested object/array as a single object then ng-class="[root.obj1, root.obj2] | mergeThings" must work (in some sense, this point at the previous one can be considered the same)

  4. There should be a clear migration path, this may include the specific example from the bug and how this should be represented, e.g the non so obvious ng-class="{[CLASS_STYLE_1]: root.obj1[CLASS_STYLE_1], [CLASS_STYLE_2]: root.obj2[CLASS_STYLE_2]}"

@OzzieOrca
Copy link

Angular 1.6.4 may not be representative of what this issue is trying to accomplish, but changing the example in my initial comment from

ng-class="{'has-error': (testForm.testInput | showErrors)}"

to

ng-class="(testForm.testInput | showErrors) && 'has-error'"

http://plnkr.co/edit/1kWniq?p=preview

or to

ng-class="{'has-error': (testForm.testInput | showErrors) && true}"

http://plnkr.co/edit/4Qx1SN?p=preview

makes it work. I'm guessing these changes turn my object into a string/boolean expression and ng-class doesn't have to handle the nested object directly any more. Idk... Will these continue to work with the changes you are proposing?

This seems a little hacky and harder to read. It would be nice for this to continue working with the object syntax like it did before to keep my code consistent but I understand the importance of dropping this for performance and cleaning up the code. I feel like I'm still trying to get around these proposed nested object restrictions. My use case may not be widely used/needed.

Idk if you guys have any better suggestions. Maybe this is just a bad practice and I should be going about it a different way. Writing a directive to work for both showing/hiding a class and showing/hiding an error message didn't seem as nice as just using ng-class and ng-if with a filter. But I suppose writing a show-error-class directive and a show-error-message directive and passing the model in wouldn't be horrible. I think I'd end up with the same number of watches though...

@jbedard
Copy link
Collaborator Author

jbedard commented May 4, 2017

@OzzieOrca I think all 3 of those examples should still be supported. But you're correct that the first one is broken in 1.6 because testInput is only shallow watched and it never changes, since it's an object it should pass it to the filter each digest even if it hasn't changed.

@jbedard
Copy link
Collaborator Author

jbedard commented Jun 13, 2017

The main issue that prompted this (#15905) has been fixed by b5118ac + b12a0b7 in v1.6.x and master.

I still think this would cleanup ng-class, make it more like Angular(2+) etc. but I don't think it will happen just for those reasons. Closing this...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants