Angular 4 Data table implementation into my APP - angular-datatables

I have created custom component DisplayTableComponent in my project. I want to incorporate Angular 4 Data table on my data for display purpose.
DisplayTableComponent.TS is as follows
import { Component, OnInit } from '#angular/core';
import { DataTableResource } from 'angular-4-data-table';
import { DataTableModule } from 'angular-4-data-table';
import persons from './data-table-demo1-data';
#Component({
selector: 'app-display-table',
templateUrl: './display-table.component.html',
styleUrls: ['./display-table.component.css']
})
export class DisplayTableComponent implements OnInit {
itemResource = new DataTableResource(persons);
items = [];
itemCount = 0;
constructor() {
this.itemResource.count().then(count => this.itemCount = count);
}
ngOnInit() {
}
reloadItems(params) {
// this.itemResource.query(params).then(items => this.items = items);
}
// special properties:
rowClick(rowEvent) {
console.log('Clicked: ' + rowEvent.row.item.name);
}
rowDoubleClick(rowEvent) {
alert('Double clicked: ' + rowEvent.row.item.name);
}
rowTooltip(item) { return item.jobTitle; }
}
My Html Template is as follows
<p>
display-table works!
</p>
<div style="margin: auto; max-width: 1000px; margin-bottom: 50px;">
<data-table id="persons-grid"
headerTitle="Employees"
[items]="items"
[itemCount]="itemCount"
(reload)="reloadItems($event)"
(rowClick)="rowClick($event)"
(rowDoubleClick)="rowDoubleClick($event)"
[rowTooltip]="rowTooltip"
>
<data-table-column
[property]="'name'"
[header]="'Name'"
[sortable]="true"
[resizable]="true">
</data-table-column>
<data-table-column
[property]="'date'"
[header]="'Date'"
[sortable]="true">
<ng-template #dataTableCell let-item="item">
<span>{{item.date | date:'yyyy-MM-dd'}}</span>
</ng-template>
</data-table-column>
<data-table-column
property="phoneNumber"
header="Phone number"
width="150px">
</data-table-column>
<data-table-column
[property]="'jobTitle'"
[header]="'Job title'"
[visible]="false">
</data-table-column>
<data-table-column
[property]="'active'"
[header]="'Active'"
[width]="100"
[resizable]="true">
<ng-template #dataTableHeader let-item="item">
<span style="color: rgb(232, 0, 0)">Active</span>
</ng-template>
<ng-template #dataTableCell let-item="item">
<span style="color: grey">
<span class="glyphicon glyphicon-ok" *ngIf="item.active"></span>
<span class="glyphicon glyphicon-remove" *ngIf="!item.active"></span>
</span>
</ng-template>
</data-table-column>
</data-table>
</div>
Now, The temporary source data file (data-table-demo1-data.ts) is as
export default [
{ 'name': 'Aaron 2Moore', 'email': 'aaa#aa.com', 'jobTitle': 'Regional Configuration Producer',
'active': true, 'phoneNumber': '611-898-6201', 'date': '2015-11-06T07:21:25.510Z' },
{ 'name': 'Yvonne Conroy Mrs.', 'email': 'sss#ssss.com', 'jobTitle': 'Global Mobility Orchestrator',
'active': false, 'phoneNumber': '115-850-0969', 'date': '2014-12-20T00:48:40.276Z' },
]
My app.Module.TS is as follows
import { BrowserModule } from '#angular/platform-browser';
import { NgModule,CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { Routes, RouterModule} from '#angular/router';
import { DataTableModule } from 'angular-4-data-table';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { MovieComponent } from './movie/movie.component';
import { DisplayTableComponent } from './display-table/display-table.component';
const appRoute: Routes =[
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{path:'home', component:HomeComponent},
{path:'Movie', component:MovieComponent},
{path:'table', component:DisplayTableComponent},
];
#NgModule({
declarations: [
AppComponent,
HomeComponent,
MovieComponent,
DisplayTableComponent
],
imports: [
BrowserModule,
RouterModule.forRoot(appRoute)
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Could you please help me. I am getting below error
ERROR in ./node_modules/angular-4-data-table/src/index.ts
Module build failed: Error: C:\projects\Handson\website1\node_modules\angular-4-data-table\src\index.ts is missing from the TypeScript compilation. Please make sure
it is in your tsconfig via the 'files' or 'include' property.
The missing file seems to be part of a third party library. TS files in published libraries are often a sign of a badly packaged library. Please open an issue in the library repository to alert its author and ask them to package the library using the Angular Package Format
at AngularCompilerPlugin.getCompiledFile (C:\projects\Handson\website1\node_modules\#ngtools\webpack\src\angular_compiler_plugin.js:656:23)
at plugin.done.then (C:\projects\Handson\website1\node_modules\#ngtools\webpack\src\loader.js:467:39)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
# ./src/app/display-table/display-table.component.ts 13:29-60
# ./src/app/app.module.ts
# ./src/main.ts
# multi webpack-dev-server/client?http://0.0.0.0:0 ./src/main.ts

It seems you are using angular 5 cli and need to integrate Angular 4 Data table on to your project.
My advice is to use angular5-data-table instead of version 4 if you are using angular 5.You can find it on https://www.npmjs.com/package/angular5-data-table

Related

Using leaflet.markercluster with a Nuxt 3 app

I'm using Leaflet with Nuxt3, TypeScript and Composition API on a production website.
As we're getting more and more markers, I'd like to use leaflet.markercluster but I can't get how to make it work properly
Here's my setup :
leaflet.client.ts
import {
LIcon,
LMap,
LMarker,
LPopup,
LTileLayer,
} from "#vue-leaflet/vue-leaflet";
import L from "leaflet";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("LMap", LMap);
nuxtApp.vueApp.component("LTileLayer", LTileLayer);
nuxtApp.vueApp.component("LMarker", LMarker);
nuxtApp.vueApp.component("LIcon", LIcon);
nuxtApp.vueApp.component("LPopup", LPopup);
return {
provide: {
L,
},
};
});
Map.vue
<client-only>
<l-map
ref="locationsMap"
:min-zoom="leafletOptions.minZoom"
:max-zoom="leafletOptions.maxZoom"
:zoom-animation="true"
:zoom="leafletOptions.zoom"
:center="leafletOptions.center"
:useGlobalLeaflet="false"
:options="{ tap: false }"
#ready="onLeafletReady">
<l-tile-layer :url="leafletOptions.url"/>
<template v-for="location in locations"
:key="location.id">
<l-marker
:lat-lng="[location.attributes.lat, location.attributes.long]"
v-if="location.attributes.active">
<div v-if="location.attributes.lat && location.attributes.long">
<l-popup class="text-center flex flex-col gap-y-4">
...
</l-popup>
<l-icon>
...
</l-icon>
</div>
</l-marker>
</template>
</l-map>
...
</client-only>
<script setup lang="ts">
import {LIcon, LMap, LMarker, LPopup, LTileLayer} from "#vue-leaflet/vue-leaflet";
import "leaflet/dist/leaflet.css";
const leafletOptions = ref({
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
minZoom: 5,
maxZoom: 13,
zoom: 5.5,
map: null,
center: [47.040182, 2.536054],
bounds: null,
overlayLocation: false,
colors: ["#ED722E", "#F6BE00", "#979B0B", "#DA2C81"],
});
// Setup and api calls to get locations
</script>
package.json
{
...,
"depencencies": {
"#vue-leaflet/vue-leaflet": "^0.7.0",
"leaflet": "^1.9.3",
"leaflet.markercluster": "^1.5.3",
},
"devDependencies": {
"nuxt": "^3.0.0",
"typescript": "^4.9.4"
"#types/leaflet.markercluster": "^1.5.1",
}
}
The thing is, now I try to group my markers by adding leaflet.markercluster. So I added something like this :
leaflet.client.ts
...
import "leaflet.markercluster";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
export default defineNuxtPlugin((nuxtApp) => {
...
return {
provide: {
L,
},
};
});
But now I don't know what to do next. Using L.markerClusterGroup() as the official documentation says does not work as we get a 500 error for using a client-side method with ssr.
I also tried to directly import in my component with import :
Map.vue
import { MarkerClusterGroup } from 'leaflet.markercluster';
const markersGroup = ref(null);
...
const onLeafletReady = async () => {
markersGroup.value = new MarkerClusterGroup() // NOT WORKING
await nextTick();
leafletObject.value = locationsMap.value;
leafletReady.value = true;
leafletObject.value.addLayer(markersGroup.value)
}
But we got the same problem as using L.anyMethod() by getting a 500 error.
I saw that Sam85 on this question has the package installed, but that was not the same problem. :/
Has anyone ever tried to make it work with Nuxt 3 ?

The bootstrap-vue <b-modal> does not appear

I need to create a modal that pop-ups when the button is clicked; i tried with bootstrap-vue, following the documentation but it didn't worked.
I put in my vue project but it doesn't work. The button is there, but when i click the modal doesn't appear. When i go to the console, it says that the directive is not recognized. I will put the code and the error below
<template>
...
<c-card>
<div>
<b-button v-b-modal.exclude class="center" size="lg" variant="danger">Excluir conta</b-button>
<b-modal id="exclude" title="bootstrapVue">
<p class="my-4">Are you sure that you want to exclude your account?</p>
</b-modal>
</div>
</c-card>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
import cCard from '#/components/Card'
import pStatusAchievements from './_partials/StatusAchievements'
import pStatusApps from './_partials/StatusApps'
import pStatusNetwork from './_partials/StatusNetwork'
import pStatus from './_partials/Status'
import pStatusPublication from './_partials/StatusPublication'
import pMyAccount from './MyAccount'
import pPowerUp from './_partials/PowerUp'
import {BModal, VBModal} from 'bootstrap-vue'
const cContentHeader = () => import('#/components/ContentMiddleHeader')
export default {
name: 'Perfil',
components: {
cContentHeader,
cCard,
pStatusPublication,
pStatusNetwork,
pStatusApps,
pMyAccount,
pStatusAchievements,
pStatus,
pPowerUp,
BModal,
},
data () {
return {
pubStatus: 1200,
networkApps: [
{ name: 'network', title: 'rede' },
{ name: 'appsUsage', title: 'uso dos apps' }
]
}
},
directives: {
'b-modal': VBModal
},
That is the vue-warn
[Vue warn]: Unknown custom element: <b-modal> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <Perfil> at src/views/perfil/Perfil.vue
<MFeed> at src/views/mobile/mFeed.vue
<SlideXLeftTransition>
<NavbarContent> at src/views/mobile/mContent.vue
<NavbarContent> at src/layouts/main/MainLayout.vue
<FadeTransition>
<App> at src/App.vue
<Root

Click event for group header on ag-grid angular

I am using ag-angular-grid in this I have group header and child columns also.
I want to know click event of that group header click.
below how I create header :
{
headerName: "<span id='performanceData'>Performance</span> <i class='fa fa-eye group-open-settings-button' aria-hidden='true' data-group='PerformanceData' ></i>",
groupId: "PerformanceData",
marryChildren: false,
onCellValueChanged:event=>{
console.log('trst');
},
children: [
{
headerName: "Talent Decision",
headerTooltip: "Talent Decision",
on click this i wants to open a popup.
any idea?
You will need to create a separate component for your custom group header. This can be done by implementing the IHeaderGroupAngularComp and using headerGroupComponentFramework, as stated on the documentation for the Header Group component.
Here is a rough sketch on how you can get it done.
First and foremost, on your main component that is using ag-grid, we will need to bind the input properties for frameworkComponents, and import your custom header group component.
On the component.html,
<ag-grid-angular style="width: 100%; height: 350px;" class="ag-theme-balham"
[columnDefs]="columnDefs"
[frameworkComponents]="frameworkComponents"
<!-- other properties -->
</ag-grid-angular>
On the component.ts, define the component which will be binded to your frameworkComponents, and for your custom header.
import { CustomHeaderGroupComponent } from '../custom-header-group-component/custom-header-group.component';
constructor() {
this.frameworkComponents = {
customHeaderGroupComponent: CustomHeaderGroupComponent,
};
this.columnDefs = [
{
headerGroupComponent: 'customHeaderGroupComponent',
// other properties for your group header
}
];
}
Do not forget to include your custom header group component on your module.ts too:
import { CustomHeaderGroupComponent } from "./custom-header-group-component/custom-header-group.component";
#NgModule({
imports: [
AgGridModule.withComponents(
[
CustomHeaderGroupComponent
]
),
// other imports
],
declarations: [
CustomHeaderGroupComponent,
// other components
],
// others
})
On your custom component.html template for the header group, you can then bind the (click) event to the header to it:
<div (click)="openPopup($event)"><span id='performanceData'>Performance</span> <i class='fa fa-eye group-open-settings-button' aria-hidden='true' data-group='PerformanceData' ></i></div>
And on your component.ts for the header group, you can define the openPopup() method:
import { Component } from '#angular/core';
import { IHeaderGroupAngularComp } from 'ag-grid-angular';
import { IHeaderGroupParams } from 'ag-grid-community';
.
.
.
export class CustomHeaderGroupComponent implements IHeaderGroupAngularComp {
params: IHeaderGroupParams;
agInit(params: IHeaderGroupParams) {
this.params = params;
}
.
.
openPopup() {
// handle the rest to enable to opening of the popup
}
}
The full working demo is actually available here, though it is a complete demo for all the features.

Angular2 template trying to render value before value returned from http.get

I have an angular2 project as follows:
package.json:
{
"name": "self-assessment",
"version": "1.0.0",
"scripts": {
"postinstall": "npm run typings install",
"lite": "lite-server",
"gulp": "gulp",
"start": "concurrent \"npm run gulp\" \"npm run lite\" ",
"typings" : "typings"
},
"license": "ISC",
"dependencies": {
"angular2": "2.0.0-beta.3",
"systemjs": "0.19.6",
"es6-promise": "^3.0.2",
"es6-shim": "^0.33.3",
"reflect-metadata": "0.1.2",
"rxjs": "5.0.0-beta.0",
"zone.js": "0.5.11"
},
"devDependencies": {
"autoprefixer": "^6.2.1",
"cssnano": "^3.4.0",
"concurrently": "^1.0.0",
"gulp": "^3.9.0",
"gulp-ext-replace": "^0.2.0",
"gulp-imagemin": "^2.4.0",
"gulp-postcss": "^6.0.1",
"gulp-sourcemaps": "^1.6.0",
"gulp-typescript": "^2.10.0",
"gulp-uglify": "^1.5.1",
"lite-server": "^2.0.1",
"postcss": "^5.0.13",
"postcss-scss": "^0.1.3",
"precss": "^1.3.0",
"typings":"^0.6.8",
"tsd": "^0.6.5-beta"
}
}
app.component.ts:
import {Component} from 'angular2/core';
import {AssessmentListComponent} from "./assessment-list.component";
import {HomeComponent} from "./home.component";
import {ApiService} from "../services/api.service";
import {RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS} from 'angular2/router';
import {AssessmentComponent} from "./assessment.component";
#Component({
selector: 'my-app',
templateUrl: 'app/components/app.component.html',
directives: [
ROUTER_DIRECTIVES,
],
providers: [
ApiService,
ROUTER_PROVIDERS,
]
})
#RouteConfig([
{path: '/home', name: 'Home', component: HomeComponent, useAsDefault: true},
{path: '/assessments', name: 'Assessments', component: AssessmentListComponent},
{path: '/assessment/:id', name: 'Assessment', component: AssessmentComponent},
])
export class AppComponent {
title = "Welcome to Self-Assessment"
}
assessment.component.ts:
import {Component, OnInit} from 'angular2/core';
import {AssessmentModel} from '../models/assessment.model';
import {RouteParams} from 'angular2/router';
import {ApiService} from '../services/api.service';
#Component({
selector: 'assessment-component',
templateUrl: 'app/components/assessment.component.html',
})
export class AssessmentComponent implements OnInit{
assessment: AssessmentModel;
errorMessage: any;
constructor(
private _apiService: ApiService,
private _routeParams: RouteParams
) {}
ngOnInit():any {
let id = +this._routeParams.get('id');
this.getAssessment(id);
}
private getAssessment(id: number) {
this._apiService.getAssessment(id)
.subscribe(
assessment => this.assessment = assessment,
error => this.errorMessage = <any>error
);
}
goBack() {
console.log(this.assessment);
}
}
api.service.ts:
import {Injectable} from 'angular2/core';
import {Http, Response} from 'angular2/http';
import {Observable} from 'rxjs/Observable';
#Injectable()
export class ApiService {
constructor(private _http: Http) {}
private _baseApiUrl = 'http://localhost:8000/';
getAssessments() {
return this.getObjectList('assessments', 'json');
}
getAssessment(id: number) {
return this.getObject('assessments', id, 'json');
}
getObjectList(listName:string, listExtension: string) {
var url = this._baseApiUrl + listName + '.' + listExtension;
return this._http.get(url)
.map(response => response.json())
.catch(this.handleError);
}
getObject(objectName:string, objectId:number, objectExtension: string) {
var url = this._baseApiUrl + objectName + '/' + objectId + '.' + objectExtension;
return this._http.get(url)
.map(response => response.json())
.catch(this.handleError);
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
}
and finally
assessment.component.html:
<h3>{{ assessment.id }}</h3>
<button (click)="goBack()">Go Back 2</button>
When the page is called with the url: http://localhost:3000/assessment/4 it makes the appropriate calls to the back-end twice and generates the following errors in the console:
Uncaught EXCEPTION: TypeError: Cannot read property 'id' of undefined in [{{ assessment.id }} in AssessmentComponent#0:4]
ORIGINAL EXCEPTION: TypeError: Cannot read property 'id' of undefined
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'id' of undefined
at AbstractChangeDetector.ChangeDetector_AssessmentComponent_0.detectChangesInRecordsInternal (viewFactory_AssessmentComponent:30:28)
at AbstractChangeDetector.detectChangesInRecords (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8116:14)
at AbstractChangeDetector.runDetectChanges (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8099:12)
at AbstractChangeDetector._detectChangesInViewChildren (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8184:14)
at AbstractChangeDetector.runDetectChanges (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8103:12)
at AbstractChangeDetector._detectChangesContentChildren (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8178:14)
at AbstractChangeDetector.runDetectChanges (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8100:12)
at AbstractChangeDetector._detectChangesInViewChildren (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8184:14)
at AbstractChangeDetector.runDetectChanges (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8103:12)
at AbstractChangeDetector.detectChanges (http://localhost:3000/node_modules/angular2/bundles/angular2.dev.js:8088:12)
ERROR CONTEXT:
[object Object]ExceptionHandler.call # angular2.dev.js:1206(anonymous function) # angular2.dev.js:12591NgZone._notifyOnError # angular2.dev.js:13635collection_1.StringMapWrapper.merge.onError # angular2.dev.js:13539Zone.run # angular2-polyfills.js:1247NgZone._notifyOnTurnDone # angular2.dev.js:13450(anonymous function) # angular2.dev.js:13565zoneBoundFn # angular2-polyfills.js:1220lib$es6$promise$asap$$flush # angular2-polyfills.js:262
So it appears as though the {{ assessment.id }} is trying to render before the object is returned from the back-end. If I then click the "Go Back 2" button it will console log the object appropriately:
{"id":4,"title":"Assessment Title here!","description":"Here is a description","questions":["http://localhost:8000/questions/1.json","http://localhost:8000/questions/2.json","http://localhost:8000/questions/3.json","http://localhost:8000/questions/4.json","http://localhost:8000/questions/5.json","http://localhost:8000/questions/6.json","http://localhost:8000/questions/7.json","http://localhost:8000/questions/8.json","http://localhost:8000/questions/9.json","http://localhost:8000/questions/10.json","http://localhost:8000/questions/11.json","http://localhost:8000/questions/12.json","http://localhost:8000/questions/13.json"],"responses":[]}
"Interestingly" I'm not seeing problems in other places in the application (ie. can load and display assessment-lists just fine, etc). Also, I'm having the exact same problem in an Ionic2 app I was working with last night as a learning project.
Have googled my butt off, hopefully somebody knows the answer to this riddle.
Thanks!
You have two options:
use the safe navigation operator (formerly called the Elvis operator), {{ assessment?.id }}, which guards against null and undefined values
use NgIf, <h3 *ngIf="assessment">{{assessment.id}}</h3>, which is more appropriate if you don't want elements added to the DOM until the data is available/populated
You likely don't have the issue with lists because NgFor handles the undefined, null or empty array case for you. Then when the data comes in, NgFor is re-evaluated.

Getting Angular2 error 'No provider for Router! (RouterOutlet -> Router)'

I use Angular2 alpha39 and Babel to transpile the ES6 JS file. I'm not using typescript.
I created a component which displays correctly. I added a router-outlet to the template. When I run the app, I get the error message:
No provider for Router! (RouterOutlet -> Router)
The call stack is:
Here is the snippet of code:
template:
.... // Removed for brevity
<div class="contenttext">
<router-outlet></router-outlet>
</div>
.... // Removed for brevity
Component file:
import { Component, View, bootstrap, OnInit } from 'angular2/angular2';
import { RouteConfig, RouterOutlet, RouterLink } from 'angular2/router';
import 'reflect-metadata';
import 'winjs';
#Component({
selector: 'dashboard-app'
})
#View({
templateUrl: '../js/dashboard.html',
directives: [ ContentComponent, FamiliesComponent, RouterOutlet, RouterLink ]
})
#RouteConfig([
{ path: '/employees', component: EmployeesComponent, as: 'employees'}
])
class DashboardAppComponent implements OnInit {
constructor() {
}
onInit() {
WinJS.UI.processAll().done(function() {
var splitView = document.querySelector(".splitView").winControl;
new WinJS.UI._WinKeyboard(splitView.paneElement);
})
}
}
bootstrap(DashboardAppComponent);
you have to use:
ROUTER_BINDINGS in your bootstrap.
in your index.html.
if possible use state i.e as "employees" in capitalize i.r as "Employees". (in alpha 42 i have solve one problem this way).
i hope this will surely help you.
--UPDATE--
after the relese of alpha41:
ROUTER_BINDINGS has been changed with ROUTER_PROVIDERS .
Router Aliases should be in the camel case manner.
for the Router-outler and router-link you just have to import ROUTER_DIRECTIVES in your directives property in the component annotation.
Router-link expects the value to be an array of route names. for more info. refer here .
for more info regarding Routing you may refer to this tutorial here .
---Update2---
Now ( as of alpha-49) router is exported as ng.router.
(According to alpha-47 all life cycle hooks renamed as.)
onActivate, onReuse, onDeactivate, canReuse, canDeactivate
To :--
routerOnActivate,routerOnReuse,routerOnDeactivate,routerCanReuse,routerCanDeactivate
---Update3---
router-link is changed to routerLink
and routeconfig property changed to:
{path: '/abc', component: ABC, as: 'abc'}
to:
{path: '/xyz' , component: XYZ, name: 'xyz'}
--Update 4 --
UPDATE TO ANGULAR2 RC
There are alot of changes has been made in routing in angular2 after RC some of them points i am going to mention here may help someone :-
angular2/router has been changed with #angular/router
(also you can use old functionality of routing using import of #angular/router-deprecated but as of now we have to use #angular/router).
#RouteConfig has been changed with #Routes .
for example :-
#Routes([
{path: '/crisis-center', component: CrisisListComponent},
{path: '/heroes', component: HeroListComponent}
])
2.0.0-alpha.36 (2015-08-31)
routerInjectables was renamed to ROUTER_BINDINGS
2.0.0-alpha.41 (2015-10-13)
ROUTER_BINDINGS was renamed to ROUTER_PROVIDERS
USE ROUTER_PROVIDERS
ROUTER_PROVIDERS is used to simplify bootstrapping the router.
It includes:
RouterRegistry - the collection of registered routes
LocationStrategy = PathLocationStrategy - match by path
ROUTER_PROVIDERS provides 'sane' defaults and should be used unless you need to need a different route LocationStrategy.
Change:
bootstrap(DashboardAppComponent);
To:
bootstrap(DashboardAppComponent, [
ROUTER_PROVIDERS
]);
Sources:
angular/commit/ccfadb9
angular/pr#4654
2.0.0-alpha.38 (2015-10-03)
Route aliases need to be CamelCase (technically PascalCase)
Note: this was mentioned already in Pardeep's answer under #3
If you want to include a link to a route in your template via router-link you have to make sure the alias (ie the name property) of the route is PascalCase.
If you use plan to use router-link modify the route to:
{ path: '/employees', component: EmployeesComponent, name: 'Employees'}
Then you can add the link in your template with:
<a [router-link]="['/Employees']">Employees Link</a>
RouterLink dynamically inserts a href that matches the route path.
Note: Reading the issue/pr it appears this change was made to prevent users from confusing the <route-link> binding with the route url
Sources:
https://groups.google.com/d/msg/angular/IF3_UCJt340/6AgSF76XAwAJ
angular/issues#4318
angular/pr#4643
Tip:
If you want to simplify your view directives use ROUTER_DIRECTIVES
It includes:
RouterLink
RouterOutlet
Update:
In the near future, RouterOutlet/<router-outlet> will be renamed to RouterViewport/<router-viewport>
Source:
angular/issues#4679
Update 2:
The RouteConfig property as has been renamed to name
Source:
angular/commit/7d83959
Answer on Dec 23rd 2016 (Angular v2.4.1, Router v3.4.1 - should work for any NG v2.x.x + Router v3.x.x)
I just migrated three of our apps from the Webpack Starter Seed to Angular CLI (v1.0.0-beta.24) and hit this issue.
Only a tiny fraction of what's on the NG 2 massive router doc page is required:
An app-routing.module.ts file (typically in src/app/ folder) looking like this sample:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
const appRoutes: Routes = [
{ path: '', component: YourHomePageComponent },
{ path: 'next-page', component: NextComponent }
];
#NgModule({
imports: [
RouterModule.forRoot(appRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule {}
Import AppRoutingModule into your main module (typically src/app/app.module.ts):
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
AppRoutingModule // <--- The import you need to add
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Ensure you have <router-outlet></router-outlet> somewhere in your main html (often src/app/app.component.html) as this is where router content is injected.
Make sure you have router defined and declared in AppModule.
Example (look everywhere where routing is mentioned, ignore the rest):
app.routing.ts
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { HeroesComponent } from './heroes.component';
import {DashboardComponent} from './dashboard.component';
import {HeroDetailComponent} from './hero-detail.component';
const appRoutes: Routes = [
{
path: 'heroes',
component: HeroesComponent
},
{
path: 'dashboard',
component: DashboardComponent
},
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
},
{
path: 'detail/:id',
component: HeroDetailComponent
},
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
and app.module.ts:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
// Imports for loading & configuring the in-memory web api
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard.component';
import { HeroesComponent } from './heroes.component';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';
import { routing } from './app.routing';
import './rxjs-extensions';
import {HeroSearchComponent} from './hero-search.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
routing
],
declarations: [
AppComponent,
DashboardComponent,
HeroDetailComponent,
HeroesComponent,
HeroSearchComponent
],
providers: [
HeroService,
],
bootstrap: [ AppComponent ]
})
export class AppModule {
}
This can save someone an hour:
You get this error if you don't even use routing (for example temporary, maybe you don't import routing config and router-outlet is commented out) BUT you are using Router or ActivatedRoute in some component constructor via dependency injection, like this:
#Component({...}})
export class SomeComponent {
constructor(private _router: Router, private _route: ActivatedRoute) {
//may be you are not using _route/_route at the moment at all!
}
...
}
You cant user Dependency Injection for Router if you dont define any routs!
To define route user something similar to following codes:
const loginRoutes: Routes = [
{path: 'foo/bar/baz', component: 'MyRootComponent'}
];
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
JsonpModule,
RouterModule.forRoot(loginRoutes)
],
providers: [],
declarations: [
MyLoginComponent
],
bootstrap: [
MyLoginComponent
]
})
export class MyLoginModule
{
}