Trying to find the answer on how to pass a common object between routes.
I have a service which store socket.io
I need to have access to that socket service across my whole site so I can listen for emits.
I have a route.ts file and I am not sure how to initialise a socket service in the root then pass it to the route when needed.
I have read the docs and I am trying to use data like below in my route.ts file:
const routes: RouterConfig = [
{ path: '', component: AppComponent },
{ path: 'function1', component: Function1Component, data: { socket: socket }},
];
However I dont know where to declare the socket service.
Thanks
In your case you are trying to pass some function reference(which is going to return object/promise/observable) from data option of route, so that would not work by passing it in data option because it does stringify the data when you ask for data by doing this.routerData.get('socket').
I strongly recommend to use resolve option of route here. resolve method would return promise/observable
Code
#Injectable()
class SocketResolver implements Resolve {
constructor(private socketService: socketService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<any> {
return this.socketService.connection();
}
}
const routes: RouterConfig = [
{ path: '', component: AppComponent },
{ path: 'function1', component: Function1Component,
resolve: { socket: SocketResolver }
}
];
Doc Link
you should not involve routing in this.
just create a service: https://angular.io/docs/ts/latest/tutorial/toh-pt4.html
SocketService.ts
import { Injectable } from '#angular/core';
#Injectable()
export class SocketService {
...
}
and inject that service in your component or other services via the constructor:
constructor(private socketService:SocketService) { }
plus you make sure your service is intialized in the bootstrap process:
bootstrap(AppComponent, [
SocketService,
... ]);
on bootstrap, angular will create a single instance of your service which will be injected into every component which has it in its constructor, therefore you have access to the same socket service from everywhere you want.
Related
What I'm trying to do is to route to different components via the same path but it wont work.
/schedule -> shall load the ScheduleComponent
/schedule/123 -> shall load the EventComponent ('123' is a dynamic path, so that it is not an option to write it to children's path)
Here is the code:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { ScheduleComponent } from './schedule.component';
import { EventComponent } from '#app/modules/event/event.component';
const routes: Routes = [
{
path: '',
component: ScheduleComponent,
children: [
{
path: '**',
component: EventComponent
}
]
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ScheduleRoutingModule { }
But I'm doing something wrong and cannot find the mistake, because the EventComponent is called in any case, even if there is no additional path given. What is wrong with my code?
Thx!
You have not specified any routes in your code example.
The '**' path that you set is used for "page not found", in case a user navigates to a non existing route.
More on routes can be found in the official documentation
const routes: Routes = [
{ path: '/schedule', component: ScheduleComponent },
{ path: '/schedule/:id', component: EventComponent },
];
What are the best practices of creating an authentication system for angular 2 SPA. Is there any built-in Angular2 modules to handle this?
The core thing you need is a guard to prevent routing to pages that require authentication. Thoughtram has a great article on guards and Jason Watmore has a brilliant post showing a full authentication mechanism using a guard and JSON Web Tokens.
Whether you use JWT (and there are reasons not to) or sessions (and there are reasons not to), it all comes down to the guard.
You write a guard like this:
#Injectable()
export class AuthGuard implements CanActivate {
constructor (private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (isTheUserSignedIn()) {
return true;
}
// If not signed in, navigate to the login page and store the return URL
this.router.navigate(['/login'], { queryParams: { returnUrl: state.url }});
return false;
}
}
And then, wherever you configure the routes for your app module, you need to tell the route to use your guard:
const appRoutes: Routes = [
// Protect the Home route using the guard
{ path: '', component: HomeComponent, canActivate: [AuthGuard] },
// Don't protect the login and register pages
{ path: 'login', component: LoginComponent },
{ path: 'register', component: RegisterComponent },
// Don't protect pages that don't need protecting
{ path: 'some-unprotected-page', component: UnprotectedPageComponent },
// Default redirect
{ path: '**', redirectTo: '' }
];
I want to make connection between my angular app and my REST API.
Here it returns JSON http://is.njn.mvm.bg/check. So my question is which providers do I need because I include in app.module, but it still doesn't work.
import { HttpModule} from '#angular/http';
I am using Angular2 HTTP tutorial
private heroesUrl = 'http://is.njn.mvm.bg/check'; // URL to web API
constructor (private http: Http) {}
getHeroes (): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
I am getting XMLHttpRequest cannot load http://localhost:8000/da. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
you are using the http request wrong. plz use following code.
app.component.ts
//our root app component
import { Component } from '#angular/core'
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'root',
template: `
<div>
{{people}}
{{ err}}
</div>
`
})
export class App {
people;
err;
constructor(http:Http) {
http.get('http://is.njn.mvm.bg/check').map(res => res.text()).subscribe(people => this.people = people,err=>this.err = err);
// Subscribe to the observable to get the parsed people object and attach it to the
// component
}
}
Also remember
Follow error occur in your console:
Access-control-allow-origin
For remove this error see:
chrome extension for access control
You need to put header parameter "Access-Control-Allow-Origin" in the server's HTTP response. You can't make this work from the client side only. I also had the same issue when trying to grab data from my Java JSON REST server. I am not sure what you use server side, but in Java it looks something like this:
return Response.ok() //200
.header("Access-Control-Allow-Origin", "*");
For information on this error (CORS), see this:
How does Access-Control-Allow-Origin header work?
You also need to add it to imports of #NgModule
#NgModule({
imports: [BrowserModule, HttpModule]
...
})
You module code will be like below:
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
],
declarations: [
AppComponent
],
providers: [
{provide: APP_BASE_HREF, useValue: '/'},
],
bootstrap: [AppComponent]
})
export class AppModule {
}
you service code need to similar to this
constructor(private http: Http) {
}
getCountriesByRegion(region: string) {
return this.http.get(this.countries_endpoint_url + region).map(res => res.json());
}
//you can also do like this
getHeroes(): Observable<any[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
You have the Angular app that's served by the server running on port 3000, but this app tries to make HTTP calls to the server running on another port 8000.
You have two options:
1. Deploy your Angular app under the server that runs on port 8000, in which case your Angular app will hit the same port it was served from.
2. Configure a proxy on the server that runs on port 3000 to allow access to port 8000.
For the second scenario, if you use Angular CLI with your project, create a file proxy-conf.json, for example:
{
"/api": {
"target": "http://localhost:8000",
"secure": false
}
}
Then sevre your Anglar app like this:
ng serve --proxy-config proxy-conf.json
Before beta.8 version, I have a working service which acts as my HTTP service.
#Page({
templateUrl: 'build/pages/log-in/log-in.html',
providers: [httpService]
})
...
this.httpService.testService("VariablesToPass").subscribe(
data => {this.results = data.results; console.log(data);},
//err => this.logError(err),
err => console.log(err),
() => console.log('Invoked Login Service Complete')
);
After the new version, configs have to move into the bootstrap, thus in my js i implemented the following :
#Component({
templateUrl: 'build/pages/log-in/log-in.html'
})
export class LoginPage {
...
}
ionicBootstrap(LoginPage, [httpService], {});
in which throws me errors like:
Using
ionicBootstrap(LoginPage, [httpService], {});
or
ionicBootstrap(LoginPage, [httpService]);
gives the same error result.
ionicBootstrap must be used only in your former #App, not in a former #Page, inject httpService there, not in LoginPage.
In your LoginPage leave the provider registration. Also, beware of your naming convention, it doesn't look right, you are using the same name for the service and its instance. It should be like this:
#Component({
templateUrl: 'build/pages/log-in/log-in.html',
providers: [HttpService]
})
class LoginPage {
constructor ( private httpService : HttpService) {}
}
also, it's beta 8, not RC
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
{
}