0

I'm using the custom tabs config but seem to have a problem loading dynamic content (components within tab panes).

The component loads promise/s or does some processing on init, and when switching to a new tab it will not switch immediately but wait until the component finishes initialization.

ie:

{{#bs-tab customTabs=true as |tab|}}

    {{#bs-nav type="tabs" as |nav|}}
        {{#nav.item active=(eq tab.activeId "edit")}}<a href="#edit" role="tab" {{action tab.select "edit"}}>Edit</a>{{/nav.item}}

     {{/bs-nav}}

    {{#tab.pane elementId="edit" title="Edit"}}
       {{#if (eq tab.activeId "edit")}}
          <h2>TEST</h2>//->this does not show until some-component finishes initialization

          {{some-component}}//->does some processing, promises or whatever on init
      {{/if}}
    {{/tab.pane}}

{{/bs-tab}}

I tried manually setting and keeping track of the activeId by hooking into the onChange event but have the same effect.

1 Answers1

0

I am not sure whether I got what you are asking correctly; but here are my opinions about your case. First of all, the component's init method runs as soon as it is rendered in the template whether or not the related tab is currently active or not. This is good in terms of application performance; because even the init methods of components for which the tabs are not visible will start running. However; you have avoided that with the following condition!

   {{#if (eq tab.activeId "edit")}}

If you use such if statements then every time you make a tab switch; a new component will be rendered and the component at the previous tab will be destroyed!!! That might kick you hard if you have some heavy work at your components; creating and destroying components would be costly. Think twice before doing so and make sure this is what you want!

If you have some stuff to display after initialization of component finishes within a tab you can make use of ember actions as usual. Please take a look at the following twiddle that I have prepared for you.

In this example, application.hbs contains two tabs in which two different components reside (my-component and my-component2). my-component init method waits for 3 seconds before being done with initialization where as my-component2 waits for 10 seconds. I have passed the same action (componentAtTabDoneInitializing) at application.js controller to both components so as the controller will be notified when each component finishes its initialization. The application controller keeps track of which component is done initializing by this way; hence you can make use if tab1FinishedInitializing, tab2FinishedInitializing flags within application.hbs.

feanor07
  • 3,328
  • 15
  • 27
  • alptugd, thank you for the response. I think you do understand my problem and it seems like your solution may work. I do want to control which components are loaded. otherwise if I have 10 tabs that means 10 components will load immediately. this is more of a user-ended problem in that the user will be forced to wait longer in that case as opposed to each tab loaded individually. –  Apr 24 '17 at 15:59
  • and you're right, it would be ideal not to reload the component once it's already loaded in once on tab switch. –  Apr 24 '17 at 16:06
  • hmm...the example you gave however doesn't help me much in regard of controlling which component loads and which doesn't. the solution isn't any different than just having all components load immediately - which can be accomplished without customTabs. I would like to think of each tab as more of a different route (without a actual different route ofcourse) where if I click on the tab, the component then loads (a loading icon is displayed etc...) and then the corresponding content is displayed. –  Apr 24 '17 at 16:31
  • this is why I have that line in there: {{#if (eq tab.activeId "edit")}} within the pane. to control the component. it's fine if I destroy the previous component. when the promises resolve once they will already be resolved for subsequent component initializations. I do not however see any drawback in destroying components - that should be reasonable in my use case. thanks again for any feedback, much appreciated. –  Apr 24 '17 at 16:37
  • just as a use case; if I have 10 tabs each which loads different content, and only one will be accessed by the user, I do not want all 10 tab components to load and make the user wait for those. also, if some of the content in each component relates to the other, I also want to prevent setting up unnecessary observers which can make this overly complicated - simply destroying and reinitializing would be ideal. –  Apr 24 '17 at 16:47
  • ok, I understand your point and you really do need the components to be re-rendered upon tab activation and be destroyed upon tab de-activation. then it is vital for you to use `{{#if (eq tab.activeId "edit")}}` condition and you can still merge what I provided I believe. – feanor07 Apr 24 '17 at 19:13
  • I think you're right. a combination of both your example should work. thanks much appreciated once more. –  Apr 24 '17 at 19:18