Will components get loading / error substates in 2.0?


#1

Hi everyone,

I’m very new to Ember.js and having a hard time getting my head around it. I read a lot and watched a couple of presentations on YouTube. From what I learned, I guess I caught the project during a period of big changes (Glimmer, lots of deprecations, 2.0,…).

Since I’m starting my first project on it now, I’m aiming straight towards 2.0 and I avoid any to-be-removed feature. From what I understood, the future will be all about components. I saw that 1.13 is going to get routable components. But what about the loading / error substates that routes had? I was a bit surprised components didn’t have such a concept already. I’d need them for non-routed components that load and keep global state.

Does anyone have an idea whether 1.13 will have the concept of loading / error substates for components?

Cheers, Mike


#2

Routeable Components has been postponed until an early 2.x release. :cry:

I believe that there would be separate components for each state. So if you had a route foobar you’d create the regular foobar component along with foobar-loading and foobar-error components. Again, I’m not 100% about that.

I am not entirely sure but I’ve heard grumblings about such thoughts. Technically you can do it within a component currently, fetching data directly on the component and using “isLoading” type {{if}} blocks, but that could get messy. A more “native” approach would be nice.


#3

Thanks for the quick reply, @Panman8201 !

Right, I read that, but forgot it in the meantime :wink: It’s a pity they won’t make it for 2.0.0. That means 2.x (as of 2.1 or 2.2, whenever the completely component-based programming model is done) will - again - have multiple ways of doing things, half of them deprecated. That will make the learning curve harder for people new to the framework.

I tried your hint with {{#if isLoading}}. The messiness wouldn’t bother me for now as my application is still pretty small. However, that doesn’t seem to work. The part in the {{#if isLoading}} is never displayed. Could you point me at an example of how to “fetch data directly on the component”?

Currently my component looks like this:

export default Ember.Component.extend({
    store: Ember.inject.service('store:main'),
    model: Ember.computed(function() {
        return this.get('store').findAll('entity');
    }),
});

and its template:

{{#if isLoading}}
    <p>Loading...</p>
{{else}}
    <ul>
        {{#each model as |item| }}
            <li>
                <!-- do stuff with item -->
            </li>
        {{/each}}
    </ul>
{{/if}}

Thanks in advance :smile:

  • Mike

#4

Already tried {{#if model.isLoading}} instead of {{#if isLoading}}?


#5

In my some of my forms components I have 3 properties for holding substate:

  • isLoaded sets to True after component loaded dependencies and is ready to display UI to user
  • isBusy sets to True when component does something and shouldn’t receive events atm (usually when user submits form)
  • loadError sets to True or error obj if component fails to load required things

For example when user opens registration form, component hits server to learn if registrations are open as well as to learn requirements for valid username and whats security question. If server answers with 200, I set isLoaded to true, thus replacing loading animation with form. Otherwhise I set loadError with whatever error server returned, and component displays it instead of loading.

When user submits form, I set isBusy to true, disabling submit button and handler.

As for how to load stuff for component, you can do it in “didInsertElement” hook.


#6

@enno: I just tried, but it doesn’t look like isLoading is automatically handled anywhere, neither on the component, nor on the model promise.

@rafalp: so if I get that right, you’re saying I’ll have to handle all substates manually through properties on the component?

didInsertElement seems to be a view hook btw. I’d rather try to avoid using controllers and views as much as possible (though I know not everything will be possible with components yet).


#7

Thats how I do it.

Don’t look at this as “using views”. Components provide those hooks for good reason. How else would you add extra JQuery magic to component that was just inserted in DOM?


#8

Oh, I didn’t see components have the didInsertElement hook too, nice! :smile:

I’m now banging my head against the wall at the next step: handling the promise returned by findAll('entity') in the component in order to update an isLoading flag after the promise fulfils, kind of what this post is about: Promises and computed properties

Would you mind helping me out with a quick example of how you solved the problem?


#9

Just a quick one off my head then:

isLoaded: false,
model: null,

loadModel: function() {
    var self = this;
    this.store.findAll('somethings').then(function(data) {
        self.setProperties({
            'isLoaded': true,
            'model': data
        });
    });
}.on('didInsertElement')

#10

Hey @rafalp, thanks a lot for your example, that’s exactly what I needed and it works like a charm :smile:

On a side note: as of Ember 1.13, components have a couple of new Lifecycle Events of which the didInitAttrs seems to be the best fitting one, I tried it and it also works as expected.