mardi 24 mars 2015

Ember.js - CSS transition not always working

I'm using Ember.js with ember-cli and ember-data. Until now, development went quite smoothly but now I encountered an issue with css transitions which I can't solve myself.


I have a list. The list contains elements which have subelements. These subelements are also rendered as a list.


I fetch the data with ember-data from a REST API. After the data is received I want to fade in (css opacity) the list. But this does not work correctly. Sometime the transition is shown and sometimes not. I'm afraid it is a timing issue. So I added Ember.run.next to my code but it didn't help. When I add setTimeout with 1ms inside Ember.run.next it works like expected (at least on my computer). This feels quite weird. Here is my code I have so far. Every feedback appreciated.


controller.js:



export default Ember.Controller.extend({
//...
objects: []
//...
_pushToMatchings: function (response) {
var tempArray = [];
var pushed = false;
for (var i = 0, length = this.get('objects.length'); i < length; i++) {
pushed = false;
var match = this.get('objects').objectAt(i);
if (match.get('meta.items').objectAt(0) === response.get('meta.items').objectAt(0)) {
tempArray.pushObject(response);
pushed = true;
} else {
tempArray.pushObject(match);
}
}
if (!pushed) {
tempArray.pushObject(response);
}
this.set('objects', tempArray);
},
fetch: function() {
var self = this;
// find parent item
this.get('store').find('item', id).then(function (item) {
self._pushToMatchings(Ember.Object.create({
meta: {
items: [id],
isLoading: true,
label: item.get('label')
},
content: []
}));
self.set('isOpen', true);
// child object
self.get('store').find('child', searchParams).then(function (result) {
(function (resultPtr) {
Ember.run.next(function () {
setTimeout(function () { // @todo why do we need timeout here? whitout there is no fade out with opacity in css possible
resultPtr.set('meta.isLoaded', true);
}, 1); // 1 is enough but give spinner some time otherwise it looks ugly
});
}(result));
result.set('meta.label', item.get('label'));
self._pushToMatchings(result);
}, function (error) { /* ... */ });
}, function (error) { /* ... */ });

}
}


controller.hbs:



<div>
{{item-list close="close" elements=objects }}
</div>


item-list.js



export default Ember.Component.extend({
elements: [],
actions: {
close: function () {
this.sendAction('close');
}
}
});


item-list.hbs



<div class="items-list__buttons">
<i class="icon-close_32" {{action "close" }}></i>
</div>
<div class="items-list__content">
{{#each matching in elements}}
<div class="items-list__item">
<h2>{{t "items.offers" }} {{matching.meta.label}}</h2>
{{spinner-element hideEvent=matching.meta.isLoaded }}
<div {{bind-attr class=":items-list__box matching.meta.isLoaded:items--fadeIn" }}>
{{#each item in matching.content}}
<div>
<!-- Render details of item -->
</div>
{{/each}}
</div>
</div>
{{/each}}
</div>


CSS:



.items-list__box {
opacity: 0;
transition: opacity 150ms ease 100ms;
}

.items--fadeIn {
opacity: 1;
}




Aucun commentaire:

Enregistrer un commentaire