I have a problem with knockout beforeRemove callback and CSS transitions

I use the foreach binding along with the beforeRemove callback to animate the removal of my list items. It works great when I delete an item over an item that I just deleted, but when I try to delete an item under a previously deleted item, the transition does not work correctly.

Here is a jsfiddle illustrating my problem: http://jsfiddle.net/tylerweeres/2szjxzs0/2/

HTML

<h3>Animations</h3>
<div data-bind="foreach: { data: people, beforeRemove: animateOut }">
    <div style="padding: 5px;" class="person">
        <span data-bind="text: name" style="display: inline-block; width: 200px;"></span>
        <button style="padding: 5px 15px;" data-bind="click: $parent.removePerson">Remove</button>
    </div>
</div>

CSS

.person {
    font-family: georgia;
    padding: 5px;
    transition: all 600ms ease-in-out;
    transform-origin: 75px;
}

.person.remove {
    transform: translateX(2000px) rotateZ(540deg);
}

Js

function vm () {
    "use strict";
    var me = this;

    me.people = ko.observableArray([
        { "name": "Irma Olsen" },
        { "name": "Winifred Cabrera" },
        // ...
        { "name": "Lucius Howard" },
        { "name": "Hedda Santana" }
    ]);

    me.removePerson = function (person) {
        me.people.remove(person);
    };

    me.animateOut = function animateOut(node, i, person) {
        // Make sure it not a text node
        if (node.nodeType == Node.ELEMENT_NODE) {
            node.classList.add("remove");
        }
    }
}

ko.applyBindings(new vm());
+4
source share
3 answers

It's weird, but I think it has to do with crazy browser logic. You need to make redraw what is not happening. At some point we have:

<div class="person remove">
<div class="person">

Then go to

<div class=person>
<div class=person>

div remove - remove, , , div, , transitionEnd, , div .

, ? , node.offsetHeight ( ).

http://jsfiddle.net/ExplosionPIlls/2szjxzs0/6/

, - , , , .

+2

documentation beforeRemove:

beforeRemove - , , DOM. beforeRemove callback, , - DOM.

beforeRemove DOM, node, .

, else node.parentElement.removeChild(node);:

me.animateOut = function animateOut(node, i, person) {
    // Make sure it not a text node
    if (node.nodeType == Node.ELEMENT_NODE) {
        node.addEventListener("transitionend", function () {
            this.parentElement.removeChild(this);
        });
        node.classList.add("remove");
    }
    else{
        node.parentElement.removeChild(node);
    }
}

JSFiddle.

+2

remove, , , .

, people, .

me.animateOut = function animateOut(node, i, person) {
    // Make sure it not a text node
    if (node.nodeType == Node.ELEMENT_NODE) {
        node.addEventListener("transitionend", function () {
            this.parentElement.removeChild(this);
            me.people.notifySubscribers(); // Add this line here
        });
        node.classList.add("remove");
    }
}

Edited Fiddle

, , undefined , .

+1
source

All Articles