I was wondering how would be the best way of doing this.
I have a list of elements that have children that will be expanded when one of those elements is clicked. There’s a button that will toggle all the elements to expand/compress their children. I have achieved all this but there’s something missed that is to recognize when all the children are expanded/compressed so I can rename the button to do what is needed, instead of, for example, show “expand all” when all are expanded and do nothing when the user clicks it.
Here’s a twiddle with the example: Ember Twiddle
Maybe the approach I’m using is not the right one and there is a more elegant way of achieving this. Any suggestion will be appreciated
I normally handle situations like this by wrapping or extending my model data to include view model data so that the parent has access to information about the view state of children.
In your example this would mean adding your expanded information to the model you pass into your item list. This is also useful if you’re saving the users view state in local storage because it allows you easily initialize the expanded state of each item-list to pickup where the user left off.
I see… so it would be like having some kind of settings for this component. What about if the model data is from ember-data? expanding the model data wouldn’t mark it as dirty?
I like to think of it as model data for the view specifically. Normally this just lives on the component but because the component needs to share this model data between multiple “views” of that data then it needs to be separated from the component class itself. In your case the shared view model data is isCollapsed per item list and the components that need access are the item lists themselves as well as the parent.
If you’re using an ember data model I normally wrap the model in a view model. This would mean that you create your list using parent-view-models instead of simply parent models. The parent view model would have the parent attribute on it. I normally use Ember.Object for the parent view model.
Example: Ember Twiddle
I’ve dome something similar to what @varblob is suggesting and it definitely works — I think there’s some good reasons for that as it’s tricky to try to manage that up and down state with truly isolated components. I think that your hesitation with that solution is also valid too as it feels like this is something that component should be able to handle.
Because I was curious what some of the challenges might be, I took a stab at this using some components and some of the new components hooks and patterns.
The basic idea is that we notify the parent component with an action whenever the child expands or collapses — including when the parent’s
allExpanded property changes.
Take a look and let me know if you think something like that might work.
The natural subsequent question I would have is how would this look if there were arbitrarily deep nested lists? *shrug*
Both approaches are very interesting and they work like charm for what I need. I’m saving both of them for future references, but the proposal of @varblob - allowing to save the user’s view state - is very tentative to let it go