• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Angular 2 Development with TypeScript: dynamically specify the content of a Material Design tab?

 
Ranch Hand
Posts: 90
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I asked this question on Stack Overflow a few days ago, but did not receive an answer.

I would like to bind the content and label of an <md-tab> from the data source. In the component source, I have an array describing the tabs that I would like to show:



I am able to bind the label using either:



.. or:



But how do I include the content within the tab?

Stack Overflow user developer033 suggested in a comment that I try binding innerHTML to the content. This allows basic markup to be displayed; however, I would like to be able to specify a template and have that be transcluded as the content of the tab. For example, if I want to add another material design component such as a button, I would like to be able to add <button md-raised-button>Raised button</button> to the content template and have a raised MD button rendered in place. This does not happen when I bind innerHTML.
 
Author
Posts: 8
5
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You cannot take an arbitrary string and turn it into a component's template. It would require to compile the string at the runtime, but even Angular's JIT compiler's minimal unit is NgModule, not a string.

If you need to dynamically create a tab's content you have several options, which one to choose depends on your particular use case. I've created an Angular demo application which shows different ways to address this problem. Here is the short descriptions of available options:

Option #1

The most idiomatic way would be to use the MdTabNavBar component instead of MdTabGroup. Tabs in MdTabNavBar do not have a content. Instead they trigger a router navigation which renders a component inside the <router-outlet>. In the router configuration you can define which route corresponds to which component. Here is a quick example:

Option #2

If the content of your tabs is limited to simple HTML markup and doesn't include Angular components, you may still use [innerHTML] however you need to use DomSanitaizer to bypass security restriction. Here is a quick example:
Component:Template:
The full example is here.

Option #3

If your tab's content includes Angular components, but you think it doesn't deserve a separate custom component, you may use ngTemplateOutlet directive. This way content of your tabs becomes part of your host component's template but it's wrapped into a <template> HTML element, so it's not rendered by browsers. Each tab references the corresponding template element. Here is a quick example:
Template:Component:
The full example is here.

Option #4

This is similar to the Option #1 but doesn't include the router part (this option may be used with MdTabGroup as well as with MdTabNavBar). The idea is to create a separate component for each tab's content and listen to tab change event. When a tab is selected we dynamically instantiate a component and render it on the page. Here is quick example:
Template:Component:
The full example is here.
 
Daniel Trebbien
Ranch Hand
Posts: 90
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Anton,

Thank you very much for your detailed reply!

I think that Option #3 is most similar to what I had in mind. What I was hoping to accomplish was to have different HTML files for the content of a fixed number of tabs. For example, if I were creating an app to list upcoming events, I wanted to be able to place the complete information about each event into a separate HTML template file; that is, I'd have event-1.html, event-2.html, etc. and the tab content would somehow include those HTML files. This way, I wouldn't have to put all information about each event into the same HTML template.

Is it possible for a <template> tag to include the content of an HTML template file?

Daniel
 
Anton S Moiseev
Author
Posts: 8
5
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's not possible. There was a hot discussion on this topic, and here is the final statement from the Angular team member - https://github.com/angular/angular/issues/7596#issuecomment-270251283.

If the events in your app are so different that it makes sense to have a separate template for each of the event types, I would suggest to split them in separate components. While it may look tedious at first, I think it promotes better code organization, improves readability, simplifies maintenance. With AoT and OnPush change detection strategy components are extremely cheap performance-wise and optionally you can load them lazily.
 
Daniel Trebbien
Ranch Hand
Posts: 90
1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's a good suggestion to create separate components. I will use this approach...
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
There is one big issue in solution #4..

When we switch the tabs, component factory will re-create the component and component will loose its state.
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic