ractivejs / ractive

Next-generation DOM manipulation
http://ractive.js.org
MIT License
5.94k stars 396 forks source link

Nested elements with transitions: possible to not trigger all? #1397

Closed rxb closed 9 years ago

rxb commented 10 years ago

Is it possible to remove a block from the document that uses a transition without also triggering all the transitions inside that block? For example:

  {{#if foo}}
    <div intro-outro="fade">
       Welcome to my cool section
       {{#if bar}}
         <div intro-outro="slide">
         Here is a single piece of that section
       </div>
       {{/if}}
    </div>
  {{/if}}

If foo becomes false, that entire block will be removed and trigger the outro, as expected. But as it fades, I can see the bar block transitioning away with its own slide outro at the same time. Ideally, only the outermost transition would happen.

This example is overly simplified, but as as my project has become more complex, I've ended up with more and more of these situations -- like a list of things which can appear or disappear as a whole, with individual list items that can also appear and disappear on their own.

martypdx commented 10 years ago

@rxb this is more of an idea at this point, of something we could maybe work into a more general solution: http://jsfiddle.net/g7fabp1j/1/

Madgvox commented 10 years ago

http://jsfiddle.net/m06jqcdn/1/

This seems to work for the most part, except you get the warning "Ractive.js: " "Missing "" transition plugin. You may need to download a transition via http://docs.ractivejs.org/latest/plugins#transitions" when it's disabled. Perhaps that should be updated so that it works the same as expressions in events?

rxb commented 10 years ago

Interesting, interesting. I could see that working in a more general sense if there was a way to detect in the element being transitioned is at the root level of the part of the dom being removed/added.

A big example of where the current behavior gets tricky is a single-page-app, where if you switch between views, every outro in the old view and every intro in the new view is going to fire all at once.

As a comparison, in Angular, both the conditional hiding/showing and the transitions are attributes of specific DOM elements -- where in Ractive, conditions wrap the DOM elements, but transitions are attributes of the DOM elements. Without the split, it's much more explicit which element should do something.

martypdx commented 10 years ago

@Madgvox :+1:

Madgvox commented 10 years ago

@rxb Perhaps a 'bubbling' property that you can set on an element? There should be some easy way to tell ractive to bubble a transition to child elements or not.

<div intro-outro='fade' intro-outro-bubble='false'>
<!-- stuff -->
</div>

A contrived example, but something like that might work. You could even set it to be dependent on an expression:

<div intro-outro='fade' intro-outro-bubble='{{ expanding }}'>
<!-- stuff -->
</div>

Or have it as a reserved parameter using the parameter object:

<div intro-outro='fade:{ bubble: false }'>
<!-- stuff -->
</div>
rxb commented 10 years ago

@Madgvox I think that could be great if Ractive needs to preserve transitions within transitions. I feel like an argument could be made that the default behavior should be that either:

rxb commented 10 years ago

Been trying to put together a demo of this but I think I'm stuck.

Is there anything in the Transition object that would tell me how far away the transitioning node is from the root node being removed/added by a condition?

Madgvox commented 10 years ago

Documentation says no. What route are you taking for implementation? I don't think that there's a way to cleanly implement this without modifying the source code.

martypdx commented 10 years ago

@rxb I don't know that we can prescribe rules about how nested transactions should work. @Madgvox's solution to declaratively modify the transition to not happen seems like the right path to me (I was going to modify thing to not warn when empty).

Your template would become:

  {{#if foo}}
    <div intro-outro="fade">
       Welcome to my cool section
       {{#if bar}}
         <div intro-outro="{{#if foo}}slide{{/}}">
         Here is a single piece of that section
       </div>
       {{/if}}
    </div>
  {{/if}}

That seems pretty clean to me.

rxb commented 10 years ago

Thanks for the help! That actually works well even in situations even where there is more than one level of nesting. Just have to check for the condition one level above it.

I do have a nagging feeling that I'm using Ractive in an overly complicated way because I'm running into this quite a bit. Maybe I should reserve Ractive transitions for true data-related changes (like adding an item to a list) and find a different way to simply hide/show things than adding attributes to model like "showFullDescription" that only serve to toggle the display.

skyrpex commented 9 years ago

I also find that the transitions should only apply to the root element being removed. I don't feel it makes sense...

The current behavior doesn't allow me to create a Collapse component in a clean way, for example.

Madgvox commented 9 years ago

Closing this as it falls under the umbrella of #1853, which is an ongoing (albeit hibernating) discussion.