No control on Blaze's reactivity updates

I have a problem with blaze that’s driving me crazy and I couldn’t find a solution after testing many ways to build UI.

I have a list that represents a list document that has a children property with an array of ids, like this:

{
    children: ["item0", "item1"]
}

each itemId corresponds to an item template that represents an item document like this:

// for item0
{
    _id: "Item0",
    text: "the text"
}

I want to be able to change the item order using the keyboard so when item1 (in position 2 in the list) is in focus and I press the up arrow the item moves to position 1 and stays in focus. To do this I change the list document with a method that first removes the item form the list.children array and then it inserts it again in the correct position.

Blaze’s reactivity changes the views correctly but I lose focus when I move the item up. Moving the item down works correctly for some reason.

I can’t find a way of detecting when the change swap is done after the update comes from minimongo.

onRendered doesn’t work because the item view is not destroyed, so it won’t get called in the new version of the item.
Tracker.afterFlush with a focus() call to the item doesn’t work either because the item loses focus after the flush.

The helper to get the items data from the ids is called twice when I move the item up and only once when I move the item down. So I don’t understand how Blaze does the update to the views.

Please help!

How do keep track of the focused item? And how do you display it?

add some item order property, update them during the move and sort it on client Collection.find using that order property

@shock I can’t add an item order property because the items can belong to many lists, each with it’s own order. Also I would like to understand why something so simple is so complicated in Blaze. I’ve had lots of problems with it, like finding sibling templates or parent/children.

@steve I think that the item should stay in focus after the change, or at least the result should be the same if I move it up and down (lose focus or don’t, not one and the other). To display it I use:

{{#each getChildrenCursor}}
	{{> item}}
{{/each}}

and the helper

getChildrenCursor: function () {
    // gets the array of children ids from the list
    var childrenIds = Items.findOne(this._id, {children:1, _id: 0}).children;
				
    var result = [];

    // finds each child from mongo and saves it to the results array.
    var total = childrenIds.length;
    for (var i = 0; i < total; i++) {
    // not using findOne because I want reactivity in viewmodel
	var child = ItemsList.find(childrenIds[i]).fetch()[0];
	if (child) {
	    result.push(child);
	}
    }
				
    return result;
},

I don’t keep track of the item in focus, but even if I do I don’t hava a way of knowing when the item was updated to focus it. I’m using manuel:viewmodel package to find children/parent/sibling templates an a few other basic things Blaze is missing.

I was able to solve this with _uihooks. With that I have control over insertion, removal and movement of the DOM elements inside a template. It’s not official but it works great. I hope Blaze 2 solves this in a good way.

http://www.webtempest.com/meteorjs-animation
https://github.com/tmeasday/transition-helper/blob/master/transition-helper.js

1 Like