Loading bar that tracks completed HTTP requests for Ember.js - ember.js

I've been looking around, and short of writing a basic one myself, I couldn't find a library that already exists for Ember that displays a small loading line at the top of the page that completes when all the http requests have completed for a page transition (whether that be images loading, JSON being fetched etc).
There's this for Angular: http://chieffancypants.github.io/angular-loading-bar/, but wondering if Ember has any options already.
Cheers.
EDIT: I've found this article as well about a jQuery plugin, which I imagine could be adapted: http://tutorialzine.com/2013/09/quick-tip-progress-bar/. Still keen on hearing if anyone knows of anything already integrated into the Ember request lifecycle though.

You can use fantastic javascript component NProgress (http://ricostacruz.com/nprogress)
and then you can initialize it in Application.ready event using jQuery like this
window.App.ready = function () {
$(document).ajaxStart(function () {
NProgress.start();
});
$(document).ajaxStop(function () {
NProgress.done();
});
};

Related

Issues with model when navigating while still being retrieved

Working with an older ember application (2.18.1). The following problem is repeated too many times to all fix in the time frame I got available right now.
The component is loading it's own data (setting this.get('model')) and all works fine.
However as the database is now a little slower the user sometimes click on one link, where the template render the component and it start loading it's data .
If the user click another link (to a route that does exactly the same) data from both the previous and the "new" component get loaded.
I can't reset the model when data get loaded, since the fetchRecord method that loads the data get called over and over with paging (as the user scroll down).
I'm sure I'm just not thinking of an obvious solution (did not work on Ember for a few years), any advise?
(ps: some of these components does not use paging, in mean time I'm going to clear out the model before setting it to what the api returns)
I'm afraid ember-data gives no support to abort a request, but you can handle that yourself directly on your component calling the endpoint through Ajax or fetch, and then pushing the payload or aborting requests using the lifecycle hooks. For example, you can trigger the abort() on the willDestroyElement hook.
import $ from 'jquery';
import Component from '#ember/component';
export default Component.extend({
init() {
this._super(...argument);
const xhr = $.get( "ajax/test.html", (data) => {
this.get('store').pushPayload(data);
});
this.set('xhr', xhr);
}
willDestroyElement() {
this._super(...argument);
this.get('xhr').abort()
}
});

How can I use piwik in an ember application?

Is there any component or plugin that I can use, to integrate piwik into an ember application?
It's very simple actually. Sadly I haven't found out yet how I can track the individual views. But this will get you going with a basic set-up that also scales well.
Put this in your ApplicationRoute it hooks the route's didTransition so that every time you transition between routes data gets send to the Piwik server.
actions: {
didTransition: function () {
Ember.run.once(this, function () {
window._paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
_paq.push(['setTrackerUrl', 'https://[Piwik server]/piwik.php']);
_paq.push(['setSiteId', 1]);
});
}
}
And don't forget to put a reference to Piwik.js in your application template to load the Piwik tracking library.
<script src="https://[Piwik server]/piwik.js" async defer></script>
There doesn't seem to be an all-integrated solution for Ember like there is for AngularJS.
You can have a look at this forum thread which may get you started.
You may also want to have a look at how it's working in AngularJS: http://luisfarzati.github.io/angulartics/ or https://github.com/mike-spainhower/angular-piwik
You can use ember-cli-piwik. It's quite simple:
Install the addon:
ember install ember-cli-piwik
Then configure it in your config/environment.js
piwik: {
sid: 123,
url: 'https://your-piwik.endpoint.com'
}
For more information, read the docs.

emberjs "loading screen" at the beginning

I don't know, if you have seen this demo-app yet: http://www.johnpapa.net/hottowel/ but once you start it, you see a really nice loading screen at the beginning like you would in any bigger desktop application/game.
So I haven't had the chance to go through the code properly myself, but I have started recently with Emberjs and I have the feeling that loading all the js-code for the whole SPA that I am building could be in the seconds area.
My question now, how would such a loading screen be possible with emberjs?
Or would there be a better way to go about that? (I somehow don't think requirejs would be a solution, though I could be wrong)
I'd like to contribute an alternate answer to this. By default, ready fires when the DOM is ready, and it may take some time to render your application after that, resulting in (possibly) a few seconds of blank page. For my application, using didInsertElement on ApplicationView was the best solution.
Example:
App.ApplicationView = Ember.View.extend({
didInsertElement: function() {
$("#loading").remove();
}
});
Please note that Ember also offers the ability to defer application readiness, see the code for more information.
Maybe it's my lazy way of doing things, but I just solved this by adding a no-ember class to my div.loading and in my CSS I added
.ember-application .no-ember {
display: none;
}
(Ember automatically adds the ember-application to the body.)
This way, you could also add CSS3 animations to transition away from the loading screen.
you can do something like this:
App = Ember.Application.create({
ready: function () {
$("#loader").remove();
}
});
in your body you set something like this
<img src="img/loading.gif" id="loader">
Alternative to using didInsertElement, the willInsertElement is a better event to perform the loading div removal since it will be removed from the body tag "before" the application template is rendered inside it and eliminates the "flicker" effect ( unless using absolute positioning of the loading div ).
Example:
App.ApplicationView = Ember.View.extend({
willInsertElement: function() {
$("#loading").remove();
}
});
Ember has an automagic loading view logic.
By simply setting App.LoadingView and its template, Ember will show that view while application loads.
This feature is likely to change in next release, in favor of a nested loading route feature which looks promising. See below:
Draft documentation
Feature proposal and discussion
In Ember 2.0 there is no more View layer, but you can do the same with initializers:
App.initializer({
name: 'splash-screen-remover',
initialize: function(application) {
$('#loading').remove();
},
});

Why does this Ember.js app work locally but not on jsFiddle.net?

Here's the fiddle. Here's the gist with the contents of my local file.
As you can see, the HTML and JavaScript are identical, and I'm loading identical versions of the jQuery, Handlebars.js, and Ember.js libraries. It works as expected locally, but does not render the application template on jsFiddle.net.
I see the following error in the Web Console:
[19:44:18.202] Error: assertion failed: You must pass at least an object and event name to Ember.addListener # https://github.com/downloads/emberjs/ember.js/ember-latest.js:51
BTW-To test the gist as a local HTML file, make sure to run it behind a web server or your browser won't download the JavaScript libs. If you have thin installed (ruby webserver), go to the directory it's in and run thin -A file start, then navigate to localhost:3000/jsfiddle-problem.html in your browser.
If you set the "Code Wrap" configuration on your fiddle to one of the options other than "onLoad" your application will work. Here is an example.
The reason for this is Ember initializes an application when the jQuery ready event fires (assuming you have not set Ember.Application.autoinit to false). With the jsFiddle "Code Wrap" configuration set to "onLoad" your application is introduced to the document after the jQuery ready event has fired, and consequently after Ember auto-initializes.
See the snippet below from ember-latest, taken on the day of this writing, which documents Ember auto-initialization being performed in a handler function passed to $().ready.
if (this.autoinit) {
var self = this;
this.$().ready(function() {
if (self.isDestroyed || self.isInitialized) return;
self.initialize();
});
}
This was strange - I couldn't get your fiddle working, specifically your {{controller.foo}} call until I disabled autoinit. I am guessing when using jsfiddle the application initialize kicks off before seeing your router. I also noticed with your fiddle the router was not logging any output even when you had enableLogging set to true.
I updated your fiddle to not use autoinit, http://jsfiddle.net/zS5uu/4/. I know a new version of ember-latest was released today, I wonder if anything about initialization changed.

Is there a way to get a callback when Ember.js has finished loading everything?

I am building an Ember.js app and I need to do some additional setup after everything is rendered/loaded.
Is there a way to get such a callback? Thanks!
There are also several functions defined on Views that can be overloaded and which will be called automatically. These include willInsertElement(), didInsertElement(), afterRender(), etc.
In particular I find didInsertElement() a useful time to run code that in a regular object-oriented system would be run in the constructor.
You can use the ready property of Ember.Application.
example from http://awardwinningfjords.com/2011/12/27/emberjs-collections.html:
// Setup a global namespace for our code.
Twitter = Em.Application.create({
// When everything is loaded.
ready: function() {
// Start polling Twitter
setInterval(function() {
Twitter.searchResults.refresh();
}, 2000);
// The default search is empty, let's find some cats.
Twitter.searchResults.set("query", "cats");
// Call the superclass's `ready` method.
this._super();
}
});
LazyBoy's answer is what you want to do, but it will work differently than you think. The phrasing of your question highlights an interesting point about Ember.
In your question you specified that you wanted a callback after the views were rendered. However, for good 'Ember' style, you should use the 'ready' callback which fires after the application is initialized, but before the views are rendered.
The important conceptual point is that after the callback updates the data-model you should then let Ember update the views.
Letting ember update the view is mostly straightforward. There are some edge cases where it's necessary to use 'didFoo' callbacks to avoid state-transition flickers in the view. (E.g., avoid showing "no items found" for 0.2 seconds.)
If that doesn't work for you, you might also investigate the 'onLoad' callback.
You can use jQuery ajax callbacks for this:
$(document).ajaxStart(function(){ console.log("ajax started")})
$(document).ajaxStop(function(){ console.log("ajax stopped")})
This will work for all ajax requests.
I simply put this into the Application Route
actions: {
loading: function(transition, route) {
this.controllerFor('application').set('isLoading', true);
this.router.on('didTransition', this, function(){
this.controllerFor('application').set('isLoading', false);
});
}
}
And then anywhere in my template I can enable and disable loading stuff using {{#if isLoading}} or I can add special jQuery events inside the actual loading action.
Very simple but effective.