Angular | How to place ng-content/child content out of component using ng-template or any
I have a tabbing component, defined in this
https://stackblitz.com/edit/angular-tabs-example
I'm trying to put ng-content from my-tabs to external ng-template, is there any way to do that ? can i assign ng-content to TemplateRef or ViewContainerRef.
angular angular2-template
add a comment |
I have a tabbing component, defined in this
https://stackblitz.com/edit/angular-tabs-example
I'm trying to put ng-content from my-tabs to external ng-template, is there any way to do that ? can i assign ng-content to TemplateRef or ViewContainerRef.
angular angular2-template
add a comment |
I have a tabbing component, defined in this
https://stackblitz.com/edit/angular-tabs-example
I'm trying to put ng-content from my-tabs to external ng-template, is there any way to do that ? can i assign ng-content to TemplateRef or ViewContainerRef.
angular angular2-template
I have a tabbing component, defined in this
https://stackblitz.com/edit/angular-tabs-example
I'm trying to put ng-content from my-tabs to external ng-template, is there any way to do that ? can i assign ng-content to TemplateRef or ViewContainerRef.
angular angular2-template
angular angular2-template
asked Nov 7 '18 at 12:30
Zain Niazi
199115
199115
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Yeah you can use @ContentChild
form angular this will help you to pass the content from parent component to child - i will change your code a bit
tabs.component.ts
@Component({
selector: 'my-tabs',
template: `
<ul class="nav nav-tabs">
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
<a href="#">{{tab.title}}</a>
</li>
</ul>
<ng-template [ngTemplateOutlet]="parentList"></ng-template>
`,
styles: [
`
.tab-close {
color: gray;
text-align: right;
cursor: pointer;
}
`
]
})
export class TabsComponent implements AfterContentInit {
@ContentChild('list') parentList: TemplateRef<any>;
}
app.component.ts
@Component({
selector: 'my-app',
template: `
<my-tabs>
<my-tab [tabTitle]="'Tab 1'">
Tab 1 content
</my-tab>
<ng-template #list>
<my-tab tabTitle="Tab 2">
Tab 2 content
</my-tab>
</ng-template>
</my-tabs>
`
})
export class AppComponent {
}
The <ng-template #list>
in the parent component will pass it's content inside the template to the child component - whereas the child component will read the content and place the content in the <ng-template [ngTemplateOutlet]="parentList"></ng-template>
By this method you can pass as many content from parent to child - hope this helps you
Thanks - Happy coding !! - Check this link for further clarification https://angular.io/api/core/ContentChild
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
yeah - you can read the template of the child component by@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this@ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the templatethis.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:52
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
add a comment |
I solved it using code below, i'm using Output EventEmitter to get ng-content and placing it in a template in parent. Any suggestions are welcome, i need help to improve it.
parent.component.html
<sb-tabs contentMode="external" (templateAfterInit)="tabContentSet($event)">
<sb-tab *ngIf="jobId" tabTitle="Invoices">
Hello
</sb-tab>
</sb-tabs>
Sidebar
Content To Show
parent.component.ts
@ViewChild("tabContent")
tabContent: TemplateRef<any>;
tabContentSet(event) {
this.tabContent = event.template;
}
tabs.component.ts
import {
Component, AfterContentInit, ContentChildren, QueryList
, Input, Output, ViewChild, EventEmitter
} from '@angular/core';
import { TabComponent } from './tab.component'
enum TabContentMode { internal = 'internal', external = 'external' }
@Component({
selector: 'sb-tabs',
template: `
<ul class="nav nav-tabs {{cssClasses.tabsBar}}">
<li class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)">
<a class="nav-link" [class.active]="tab.active">{{tab.title}}</a>
</li>
</ul>
<ng-container *ngIf="contentMode == 'internal'" [ngTemplateOutlet]="tabsContent">
</ng-container>
<ng-template #tabsContent>
<ng-content></ng-content>
</ng-template>
`
})
export class TabsComponent implements AfterContentInit {
@Input() cssClasses: any = {
tabsBar: 'nav nav-tabs'
};
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
@ViewChild("tabsContent")
private externalTemplate: any;
@Input() contentMode: TabContentMode = TabContentMode.internal;
@Output("templateAfterInit")
templateAfterInit = new EventEmitter();
constructor() { }
ngAfterContentInit(): void {
this.templateAfterInit.emit({ template: this.externalTemplate });
// get all active tabs
let activeTabs = this.tabs.filter((tab) => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: TabComponent) {
// deactivate all tabs
this.tabs.toArray().forEach(tab => tab.active = false);
// activate the tab the user has clicked on.
tab.active = true;
}
}
tab.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { fadeInOut } from '@shared/common/animations';
@Component({
selector: 'sb-tab',
animations: [fadeInOut],
template: `
<div [@fadeInOut] *ngIf="active" class="pane">
<ng-content></ng-content>
</div>
`
})
export class TabComponent implements OnInit {
@Input('tabTitle') title: string;
@Input() active = false;
constructor() { }
ngOnInit() {
}
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53189526%2fangular-how-to-place-ng-content-child-content-out-of-component-using-ng-templa%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Yeah you can use @ContentChild
form angular this will help you to pass the content from parent component to child - i will change your code a bit
tabs.component.ts
@Component({
selector: 'my-tabs',
template: `
<ul class="nav nav-tabs">
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
<a href="#">{{tab.title}}</a>
</li>
</ul>
<ng-template [ngTemplateOutlet]="parentList"></ng-template>
`,
styles: [
`
.tab-close {
color: gray;
text-align: right;
cursor: pointer;
}
`
]
})
export class TabsComponent implements AfterContentInit {
@ContentChild('list') parentList: TemplateRef<any>;
}
app.component.ts
@Component({
selector: 'my-app',
template: `
<my-tabs>
<my-tab [tabTitle]="'Tab 1'">
Tab 1 content
</my-tab>
<ng-template #list>
<my-tab tabTitle="Tab 2">
Tab 2 content
</my-tab>
</ng-template>
</my-tabs>
`
})
export class AppComponent {
}
The <ng-template #list>
in the parent component will pass it's content inside the template to the child component - whereas the child component will read the content and place the content in the <ng-template [ngTemplateOutlet]="parentList"></ng-template>
By this method you can pass as many content from parent to child - hope this helps you
Thanks - Happy coding !! - Check this link for further clarification https://angular.io/api/core/ContentChild
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
yeah - you can read the template of the child component by@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this@ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the templatethis.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:52
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
add a comment |
Yeah you can use @ContentChild
form angular this will help you to pass the content from parent component to child - i will change your code a bit
tabs.component.ts
@Component({
selector: 'my-tabs',
template: `
<ul class="nav nav-tabs">
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
<a href="#">{{tab.title}}</a>
</li>
</ul>
<ng-template [ngTemplateOutlet]="parentList"></ng-template>
`,
styles: [
`
.tab-close {
color: gray;
text-align: right;
cursor: pointer;
}
`
]
})
export class TabsComponent implements AfterContentInit {
@ContentChild('list') parentList: TemplateRef<any>;
}
app.component.ts
@Component({
selector: 'my-app',
template: `
<my-tabs>
<my-tab [tabTitle]="'Tab 1'">
Tab 1 content
</my-tab>
<ng-template #list>
<my-tab tabTitle="Tab 2">
Tab 2 content
</my-tab>
</ng-template>
</my-tabs>
`
})
export class AppComponent {
}
The <ng-template #list>
in the parent component will pass it's content inside the template to the child component - whereas the child component will read the content and place the content in the <ng-template [ngTemplateOutlet]="parentList"></ng-template>
By this method you can pass as many content from parent to child - hope this helps you
Thanks - Happy coding !! - Check this link for further clarification https://angular.io/api/core/ContentChild
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
yeah - you can read the template of the child component by@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this@ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the templatethis.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:52
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
add a comment |
Yeah you can use @ContentChild
form angular this will help you to pass the content from parent component to child - i will change your code a bit
tabs.component.ts
@Component({
selector: 'my-tabs',
template: `
<ul class="nav nav-tabs">
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
<a href="#">{{tab.title}}</a>
</li>
</ul>
<ng-template [ngTemplateOutlet]="parentList"></ng-template>
`,
styles: [
`
.tab-close {
color: gray;
text-align: right;
cursor: pointer;
}
`
]
})
export class TabsComponent implements AfterContentInit {
@ContentChild('list') parentList: TemplateRef<any>;
}
app.component.ts
@Component({
selector: 'my-app',
template: `
<my-tabs>
<my-tab [tabTitle]="'Tab 1'">
Tab 1 content
</my-tab>
<ng-template #list>
<my-tab tabTitle="Tab 2">
Tab 2 content
</my-tab>
</ng-template>
</my-tabs>
`
})
export class AppComponent {
}
The <ng-template #list>
in the parent component will pass it's content inside the template to the child component - whereas the child component will read the content and place the content in the <ng-template [ngTemplateOutlet]="parentList"></ng-template>
By this method you can pass as many content from parent to child - hope this helps you
Thanks - Happy coding !! - Check this link for further clarification https://angular.io/api/core/ContentChild
Yeah you can use @ContentChild
form angular this will help you to pass the content from parent component to child - i will change your code a bit
tabs.component.ts
@Component({
selector: 'my-tabs',
template: `
<ul class="nav nav-tabs">
<li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active">
<a href="#">{{tab.title}}</a>
</li>
</ul>
<ng-template [ngTemplateOutlet]="parentList"></ng-template>
`,
styles: [
`
.tab-close {
color: gray;
text-align: right;
cursor: pointer;
}
`
]
})
export class TabsComponent implements AfterContentInit {
@ContentChild('list') parentList: TemplateRef<any>;
}
app.component.ts
@Component({
selector: 'my-app',
template: `
<my-tabs>
<my-tab [tabTitle]="'Tab 1'">
Tab 1 content
</my-tab>
<ng-template #list>
<my-tab tabTitle="Tab 2">
Tab 2 content
</my-tab>
</ng-template>
</my-tabs>
`
})
export class AppComponent {
}
The <ng-template #list>
in the parent component will pass it's content inside the template to the child component - whereas the child component will read the content and place the content in the <ng-template [ngTemplateOutlet]="parentList"></ng-template>
By this method you can pass as many content from parent to child - hope this helps you
Thanks - Happy coding !! - Check this link for further clarification https://angular.io/api/core/ContentChild
answered Nov 7 '18 at 12:50
Rahul
1,0131315
1,0131315
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
yeah - you can read the template of the child component by@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this@ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the templatethis.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:52
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
add a comment |
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
yeah - you can read the template of the child component by@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this@ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the templatethis.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:52
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
Thanks for help, but what i want to do is getting these rendered components out of my-tabs component and placing it anywhere in parent using templateref or anything like it. what you are doing is passing template from parent to child and placing it in child.
– Zain Niazi
Nov 8 '18 at 7:43
yeah - you can read the template of the child component by
@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this @ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the template this.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…– Rahul
Nov 8 '18 at 7:52
yeah - you can read the template of the child component by
@ViewChild('templateName') templatePropName : TemplateRef<any>;
and to read this template from the parent you need to read the entire child component like this @ViewChild(ChildComponentName) childPropName : ChildComponentName
- this will act as instance to the child component where you can read the template this.childPropName.templatePropName
so you will get your template and you can place it anywhere in your parent - Ref [angular.io/guide/…– Rahul
Nov 8 '18 at 7:52
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
Reference - [angular.io/guide/…
– Rahul
Nov 8 '18 at 7:58
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
I have placed my solution. If you can suggest any improvements, those will be much appreciated.
– Zain Niazi
Nov 19 '18 at 12:06
add a comment |
I solved it using code below, i'm using Output EventEmitter to get ng-content and placing it in a template in parent. Any suggestions are welcome, i need help to improve it.
parent.component.html
<sb-tabs contentMode="external" (templateAfterInit)="tabContentSet($event)">
<sb-tab *ngIf="jobId" tabTitle="Invoices">
Hello
</sb-tab>
</sb-tabs>
Sidebar
Content To Show
parent.component.ts
@ViewChild("tabContent")
tabContent: TemplateRef<any>;
tabContentSet(event) {
this.tabContent = event.template;
}
tabs.component.ts
import {
Component, AfterContentInit, ContentChildren, QueryList
, Input, Output, ViewChild, EventEmitter
} from '@angular/core';
import { TabComponent } from './tab.component'
enum TabContentMode { internal = 'internal', external = 'external' }
@Component({
selector: 'sb-tabs',
template: `
<ul class="nav nav-tabs {{cssClasses.tabsBar}}">
<li class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)">
<a class="nav-link" [class.active]="tab.active">{{tab.title}}</a>
</li>
</ul>
<ng-container *ngIf="contentMode == 'internal'" [ngTemplateOutlet]="tabsContent">
</ng-container>
<ng-template #tabsContent>
<ng-content></ng-content>
</ng-template>
`
})
export class TabsComponent implements AfterContentInit {
@Input() cssClasses: any = {
tabsBar: 'nav nav-tabs'
};
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
@ViewChild("tabsContent")
private externalTemplate: any;
@Input() contentMode: TabContentMode = TabContentMode.internal;
@Output("templateAfterInit")
templateAfterInit = new EventEmitter();
constructor() { }
ngAfterContentInit(): void {
this.templateAfterInit.emit({ template: this.externalTemplate });
// get all active tabs
let activeTabs = this.tabs.filter((tab) => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: TabComponent) {
// deactivate all tabs
this.tabs.toArray().forEach(tab => tab.active = false);
// activate the tab the user has clicked on.
tab.active = true;
}
}
tab.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { fadeInOut } from '@shared/common/animations';
@Component({
selector: 'sb-tab',
animations: [fadeInOut],
template: `
<div [@fadeInOut] *ngIf="active" class="pane">
<ng-content></ng-content>
</div>
`
})
export class TabComponent implements OnInit {
@Input('tabTitle') title: string;
@Input() active = false;
constructor() { }
ngOnInit() {
}
}
add a comment |
I solved it using code below, i'm using Output EventEmitter to get ng-content and placing it in a template in parent. Any suggestions are welcome, i need help to improve it.
parent.component.html
<sb-tabs contentMode="external" (templateAfterInit)="tabContentSet($event)">
<sb-tab *ngIf="jobId" tabTitle="Invoices">
Hello
</sb-tab>
</sb-tabs>
Sidebar
Content To Show
parent.component.ts
@ViewChild("tabContent")
tabContent: TemplateRef<any>;
tabContentSet(event) {
this.tabContent = event.template;
}
tabs.component.ts
import {
Component, AfterContentInit, ContentChildren, QueryList
, Input, Output, ViewChild, EventEmitter
} from '@angular/core';
import { TabComponent } from './tab.component'
enum TabContentMode { internal = 'internal', external = 'external' }
@Component({
selector: 'sb-tabs',
template: `
<ul class="nav nav-tabs {{cssClasses.tabsBar}}">
<li class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)">
<a class="nav-link" [class.active]="tab.active">{{tab.title}}</a>
</li>
</ul>
<ng-container *ngIf="contentMode == 'internal'" [ngTemplateOutlet]="tabsContent">
</ng-container>
<ng-template #tabsContent>
<ng-content></ng-content>
</ng-template>
`
})
export class TabsComponent implements AfterContentInit {
@Input() cssClasses: any = {
tabsBar: 'nav nav-tabs'
};
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
@ViewChild("tabsContent")
private externalTemplate: any;
@Input() contentMode: TabContentMode = TabContentMode.internal;
@Output("templateAfterInit")
templateAfterInit = new EventEmitter();
constructor() { }
ngAfterContentInit(): void {
this.templateAfterInit.emit({ template: this.externalTemplate });
// get all active tabs
let activeTabs = this.tabs.filter((tab) => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: TabComponent) {
// deactivate all tabs
this.tabs.toArray().forEach(tab => tab.active = false);
// activate the tab the user has clicked on.
tab.active = true;
}
}
tab.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { fadeInOut } from '@shared/common/animations';
@Component({
selector: 'sb-tab',
animations: [fadeInOut],
template: `
<div [@fadeInOut] *ngIf="active" class="pane">
<ng-content></ng-content>
</div>
`
})
export class TabComponent implements OnInit {
@Input('tabTitle') title: string;
@Input() active = false;
constructor() { }
ngOnInit() {
}
}
add a comment |
I solved it using code below, i'm using Output EventEmitter to get ng-content and placing it in a template in parent. Any suggestions are welcome, i need help to improve it.
parent.component.html
<sb-tabs contentMode="external" (templateAfterInit)="tabContentSet($event)">
<sb-tab *ngIf="jobId" tabTitle="Invoices">
Hello
</sb-tab>
</sb-tabs>
Sidebar
Content To Show
parent.component.ts
@ViewChild("tabContent")
tabContent: TemplateRef<any>;
tabContentSet(event) {
this.tabContent = event.template;
}
tabs.component.ts
import {
Component, AfterContentInit, ContentChildren, QueryList
, Input, Output, ViewChild, EventEmitter
} from '@angular/core';
import { TabComponent } from './tab.component'
enum TabContentMode { internal = 'internal', external = 'external' }
@Component({
selector: 'sb-tabs',
template: `
<ul class="nav nav-tabs {{cssClasses.tabsBar}}">
<li class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)">
<a class="nav-link" [class.active]="tab.active">{{tab.title}}</a>
</li>
</ul>
<ng-container *ngIf="contentMode == 'internal'" [ngTemplateOutlet]="tabsContent">
</ng-container>
<ng-template #tabsContent>
<ng-content></ng-content>
</ng-template>
`
})
export class TabsComponent implements AfterContentInit {
@Input() cssClasses: any = {
tabsBar: 'nav nav-tabs'
};
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
@ViewChild("tabsContent")
private externalTemplate: any;
@Input() contentMode: TabContentMode = TabContentMode.internal;
@Output("templateAfterInit")
templateAfterInit = new EventEmitter();
constructor() { }
ngAfterContentInit(): void {
this.templateAfterInit.emit({ template: this.externalTemplate });
// get all active tabs
let activeTabs = this.tabs.filter((tab) => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: TabComponent) {
// deactivate all tabs
this.tabs.toArray().forEach(tab => tab.active = false);
// activate the tab the user has clicked on.
tab.active = true;
}
}
tab.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { fadeInOut } from '@shared/common/animations';
@Component({
selector: 'sb-tab',
animations: [fadeInOut],
template: `
<div [@fadeInOut] *ngIf="active" class="pane">
<ng-content></ng-content>
</div>
`
})
export class TabComponent implements OnInit {
@Input('tabTitle') title: string;
@Input() active = false;
constructor() { }
ngOnInit() {
}
}
I solved it using code below, i'm using Output EventEmitter to get ng-content and placing it in a template in parent. Any suggestions are welcome, i need help to improve it.
parent.component.html
<sb-tabs contentMode="external" (templateAfterInit)="tabContentSet($event)">
<sb-tab *ngIf="jobId" tabTitle="Invoices">
Hello
</sb-tab>
</sb-tabs>
Sidebar
Content To Show
parent.component.ts
@ViewChild("tabContent")
tabContent: TemplateRef<any>;
tabContentSet(event) {
this.tabContent = event.template;
}
tabs.component.ts
import {
Component, AfterContentInit, ContentChildren, QueryList
, Input, Output, ViewChild, EventEmitter
} from '@angular/core';
import { TabComponent } from './tab.component'
enum TabContentMode { internal = 'internal', external = 'external' }
@Component({
selector: 'sb-tabs',
template: `
<ul class="nav nav-tabs {{cssClasses.tabsBar}}">
<li class="nav-item" *ngFor="let tab of tabs" (click)="selectTab(tab)">
<a class="nav-link" [class.active]="tab.active">{{tab.title}}</a>
</li>
</ul>
<ng-container *ngIf="contentMode == 'internal'" [ngTemplateOutlet]="tabsContent">
</ng-container>
<ng-template #tabsContent>
<ng-content></ng-content>
</ng-template>
`
})
export class TabsComponent implements AfterContentInit {
@Input() cssClasses: any = {
tabsBar: 'nav nav-tabs'
};
@ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
@ViewChild("tabsContent")
private externalTemplate: any;
@Input() contentMode: TabContentMode = TabContentMode.internal;
@Output("templateAfterInit")
templateAfterInit = new EventEmitter();
constructor() { }
ngAfterContentInit(): void {
this.templateAfterInit.emit({ template: this.externalTemplate });
// get all active tabs
let activeTabs = this.tabs.filter((tab) => tab.active);
// if there is no active tab set, activate the first
if (activeTabs.length === 0) {
this.selectTab(this.tabs.first);
}
}
selectTab(tab: TabComponent) {
// deactivate all tabs
this.tabs.toArray().forEach(tab => tab.active = false);
// activate the tab the user has clicked on.
tab.active = true;
}
}
tab.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { fadeInOut } from '@shared/common/animations';
@Component({
selector: 'sb-tab',
animations: [fadeInOut],
template: `
<div [@fadeInOut] *ngIf="active" class="pane">
<ng-content></ng-content>
</div>
`
})
export class TabComponent implements OnInit {
@Input('tabTitle') title: string;
@Input() active = false;
constructor() { }
ngOnInit() {
}
}
answered Nov 19 '18 at 12:05
Zain Niazi
199115
199115
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53189526%2fangular-how-to-place-ng-content-child-content-out-of-component-using-ng-templa%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown