1

I want to create a dynamic tabs navigation system using Angular 2.

Basically I want to first display a single tab that contains a single component, containing clickable objects (like links, buttons...).

I would like that a click on one of those links adds a new tab, and that a click on each tab (the initial one and the newly created tab) displays a corresponding component in display zone (router-outlet) below.

This is what I've tried so far:

app.component.ts (Root component and "tabs container):

import { Component, OnInit } from '@angular/core';
import { TabComponent } from './tab/tab.component';
import { FirstComponent } from './test/first.component';
import { SecondComponent } from './test/second.component';
import { ThirdComponent } from './test/third.component';
import { ROUTER_DIRECTIVES } from '@angular/router';

@Component({
  selector: 'my-app',
  templateUrl: './app/app.component.html',
  directives: [TabComponent, ROUTER_DIRECTIVES, FirstComponent, SecondComponent, ThirdComponent],
})

export class AppComponent implements OnInit{ 

	tabList: any[];

	constructor() {}

	ngOnInit() {
		this.tabList = [
			{
				name: 'link 1',
				link: "/comp1"
			},
			{
				name: 'link 2',
				link: "/comp2"
			},
			{
				name: 'link 3',
				link: "/comp3"
			}
		]		
	}
}

app.component.html:

<h1>Tabs container</h1>
<div>
	<nav>
		<tab *ngFor="let tab of tabList" [name]="tab.name" [link]="tab.link"></tab>
	</nav>    
</div>
<div>
    <router-outlet></router-outlet>
</div>

Each tab is represented by a tab.component.ts:

import { ROUTER_DIRECTIVES, Router } from '@angular/router';
import { Component, OnInit, Input  } from '@angular/core';

@Component({
	selector: 'tab',
	templateUrl: './app/tab/tab.component.html',
  	directives: [ROUTER_DIRECTIVES]
})

export class TabComponent implements OnInit {
	@Input() name: string;
	@Input() link: string;
	@Input() param: string;
	targetArray: Array<any>;

	constructor(private router: Router) {}

	ngOnInit() {
		
	}

	
}	

which template is tab.component.html:

<a [routerLink]='link'>{{name}}</a>

Here is the app.routes.ts file:

import { provideRouter, RouterConfig } from '@angular/router';
import { TabComponent } from './tab/tab.component';
import { FirstComponent } from './test/first.component';
import { SecondComponent } from './test/second.component';
import { ThirdComponent } from './test/third.component';

export const routes: RouterConfig = [
  {
    path: '',
    component: TabComponent
  },
  {
    path: 'comp1',
    component: FirstComponent
  },
  {
    path: 'comp2',
    component: SecondComponent
  },
  {
    path: 'comp3',
    component: ThirdComponent
  },
];

export const APP_ROUTER_PROVIDERS = [
  provideRouter(routes)
];

Here is for example the first.component.ts (SecondComponent and ThirdComponent are similar):

import { Component, OnInit } from '@angular/core';

@Component({
	selector: 'first',
	template: `<h1>First</h1>
 			   <button (click)="addTab()">Display child</button>
	           `
})
export class FirstComponent implements OnInit {
	constructor() {}

	ngOnInit() {
		
	}

	addTab(){
	}
}
	

I would like to put the tab creation logic in the addTab() method to basically add an element to the tabList array in app.component.ts and obtain the desired behavior but I don't know how to transfer data from this component to the app.component.ts.

I also open to any different approach and suggestions.

1 Answer 1

1

You can inject the Router into your component and use the config method to configure dynamic links.

router.config([
  { 'path': '/', 'component': IndexComp },
  { 'path': '/user/:id', 'component': UserComp },
]);

The documentation for the Router service can be found here.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your answer @toskv, but I'm not sure I understand, do you mean I should replace the tabList array in app.component.ts by the router.config you proposed? I actually want to be able to add a new tab dynamically when a corresponding button/link is clicked in the component currently displayed by the router-outlet and to display a corresponding component in the new tab, in regards of what I've done so fare, I thought I should find a way to add elements to the tabList array from the component displayed in the router-outlet which would add a new tab.
that's the general ideea. Sadly there doesn't seem to be a way to add a route to the current config, so you have to replace all of them. :(
Is it possible tha an "outlet"component can communicate with a parent component using a shared service?
I don't see why not. As long as they share the same service instance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.