Angular 2 landing page - javascript

I am taking my first steps with Angular 2 and angular in general, and I am wondering how to setup a landing page.
My goal is to show a landingpage everytime the user does not have a token in local storage or in a cookie.
My app.component.ts looks like this
import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES, RouteConfig} from 'angular2/router';
import {NavbarComponent} from './navbar.component';
import {LoaderComponent} from './loader.component';
import {NameListService} from '../shared/index';
import {HomeComponent} from '../+home/index';
import {AboutComponent} from '../+about/index';
#Component({
selector: 'g-app',
viewProviders: [NameListService],
templateUrl: 'app/components/app.component.html',
directives: [ROUTER_DIRECTIVES, NavbarComponent, LoaderComponent]
})
#RouteConfig([
{
path: '/',
name: 'Home',
component: HomeComponent
},
{
path: '/about',
name: 'About',
component: AboutComponent
}
])
export class AppComponent {
}
/home and /about are also components if I understand correctly. Now I would like to have a seperate page that doesn't have access to the navbar. Which is what the user will always land on if he isn't logged in.
Would be awesome if someone could help me start out or atleast point me in a good direction, maybe point me to a good angular 2 tutorial.
This is the boilerplate I am basing my app on https://github.com/mgechev/angular2-seed

You can override the router-outlet and check on activation, if the token is present. Something like this:
import {Directive, Attribute, ElementRef, DynamicComponentLoader} from 'angular2/core';
import {Router, RouterOutlet, ComponentInstruction} from 'angular2/router';
#Directive({
selector: 'router-outlet'
})
export class LoggedInRouterOutlet extends RouterOutlet {
publicRoutes: any;
private parentRouter: Router;
constructor(_elementRef: ElementRef, _loader: DynamicComponentLoader,
_parentRouter: Router, #Attribute('name') nameAttr: string) {
super(_elementRef, _loader, _parentRouter, nameAttr);
this.parentRouter = _parentRouter;
}
activate(instruction: ComponentInstruction) {
if (!hasToken()) {
this.parentRouter.navigateByUrl('/login');
}
return super.activate(instruction);
}
}
Adapted from here: https://github.com/auth0-blog/angular2-authentication-sample/blob/master/src/app/LoggedInOutlet.ts
This can be extended to be able to work with roles and other access controlls.

You can just redirect to a specific route on load when the token is not available.
export class AppComponent {
constructor(private router:Router) {
if(!hasToken()) {
router.navigate(['/LoginForm']);
}
}
}
Alternatively you can create a custom RouterOutlet that checks for each route if it is allowed for the user to navigate to that route like explained in http://www.captaincodeman.com/2016/03/31/angular2-route-security/

Related

How do i add properly create a component to my Jhipster + Angular project with a workin routerlink?

SO i generated a new application on jhipster and i have wanted to create a front side FAQ page for my web portal, i created it as an entity and it generated all the CRUD components (detail, delete, edit). This of course in the jhipster template looks like an admin/user view table with buttons to view, edit or delete. I want to make the FAQ public to visitors of the website without needing to have an account...
So i generated a component 'faq-page' like the documentation says: https://www.jhipster.tech/using-angular/ only problem is the routerlink does not redirect me to '/faq' instead it redirects me to the 404 page. I created the 'faq-page' component based on the existing 'home' like below snippets:
faq-page.component.html (just has some texts for now)
faq-page.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'jhi-faq-page',
templateUrl: './faq-page.component.html',
styleUrls: ['./faq-page.component.scss']
})
export class FaqPageComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
faq-page.module.ts
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { TestAppSharedModule } from 'app/shared/shared.module';
import { FAQ_PAGE_ROUTE } from './faq-page.route';
import { FaqPageComponent } from './faq-page.component'
#NgModule({
imports: [RouterModule.forChild([FAQ_PAGE_ROUTE]), TestAppSharedModule ],
declarations: [FaqPageComponent]
})
export class FaqModule { }
faq-page.route.ts
import { Route } from '#angular/router';
import { FaqPageComponent } from './faq-page.component';
export const FAQ_PAGE_ROUTE: Route = {
path: 'faq',
component: FaqPageComponent,
data: {
authorities: [],
pageTitle: 'faq-page.title'
}
};
Check your app-routing.module.ts and make sure the ...LAYOUT_ROUTES, line comes last!
ng generate will add your new component at the end, which will let the catch-all 404 page (contained in LAYOUT_ROUTES) match before your new page.
This needs to be printed somewhere in large friendly letters.

Read route params from directly entered url in app

My question would be regarding angular 4, how to get route params, if for example a user gets on your page with, instead of the default url, like for example http://localhost:3000/, to something like http://localhost:3000/user/:id, and to be able to pick up the :id from that url (user has directly entered it in the browser, not navigating through the app).
In the example bellow same component is used, mainly because of needing to catch that id and dispatch other actions, if its present, and that would be it.
I have tried playing around with ActivatedRoute but from what I could tell so far, that only works when navigation throughout the app, from within the app, not in this case, which always returns a null value if that url is directly entered in the browser, it gets redirected to the default / route and that would be it.
Any tips or pointers are much appreciated
app.routing-module.ts
import {hookComponent} from './hook.component';
import {RouterModule, Routes} from '#angular/router';
import {NgModule} from '#angular/core';
export const routes: Routes = [
{
path: '',
component: HookComponent
},
{
path: 'user/:id',
component: HookComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
exports: [RouterModule]
})
export class AppRoutingModule {}
hook.component
import {Component, EventEmitter, Input, OnInit, ViewChild} from '#angular/core';
import { ActivatedRoute, ParamMap} from '#angular/router';
#Component({
selector: 'hook',
templateUrl: 'hook.component.html',
styleUrls: ['hook.component.scss']
})
export class HookComponent implements OnDestroy, OnInit {
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
this.sub = this.route.params.subscribe(params => {
console.log('params are', params); //null?
});
}
}
Your way is already ok, but in your example params is an array and you can access to :id by calling params['id']:
this.sub = this.route.params.subscribe(params => {
console.log('params are', params['id']);
});
Here is an working example on stackblitz.
Access current url via Location
public constructor(location:Location) {
let url = location.prepareExternalUrl(location.path());
}
and parse out id from this.
If all you want to do is log the params.id; try using the ActivatedRouteSnapshot like this.
ngOnInit() {
console.log(this.route.snapshot.params.id);
}
If you want to check if the params.id is present, maybe do something like:
import {Component, EventEmitter, Input, OnInit, ViewChild} from '#angular/core';
import { ActivatedRoute, ParamMap} from '#angular/router';
#Component({
selector: 'hook',
templateUrl: 'hook.component.html',
styleUrls: ['hook.component.scss']
})
export class HookComponent implements OnDestroy, OnInit {
hasId: boolean = false;
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
if(this.route.snapshot.params.id !== null)
{
// do magic....
}
}
}

Supplied parameters do not match any signature of call target error is thrown on Instantiating of Class

I am trying to wrap each of router.navigateByUrl in a function of a class and plan to call that function in relevant place. But doing so throwing 'Supplied parameters do not match any signature of call target'. I have followed few other links in SO but none seems to be helpful in my case
commonRouter.ts
// have wrapped navigation to home in homePage
// so wherever is needed this homePage will be called instead of
//this.router.navigateByUrl('/home');
import {Router} from '#angular/router';
export class RouterComponent{
router:any;
constructor(private rt:Router){
this.router=rt;
}
homePage(){
this.router.navigateByUrl('/home');
}
}
someComponent.ts
// Importing the newly created typescript file
import {RouterComponent} from './../../app-routing-component';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.less']
})
export class LoginComponent implements OnInit {
private ms:MainService= new MainService();
//Instantiating RouterComponent
private rt:RouterComponent = new RouterComponent(); // this line throwing error
constructor(private fb:FormBuilder) {}
someMethod(){
rt.homePage() // Calling homePage
}
//... rest of code
}
app-routing.module.ts
// module where all the paths and component are declared
import {NgModule} from "#angular/core";
import {RouterModule, Routes} from "#angular/router";
import {HomeComponent} from "./home/home/home.component";
const routes: Routes = [
{
path: 'login', component: LoginComponent,
}, {
path: 'home', component: HomeComponent,
children: [{
path: "account",
component: AccountsComponent
},{
path: '**',
component: PageNotFoundComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {
}
Your RouterComponent requires a Router argument. Router is an injectable, thus would be resolvable if Angular knows how to handle your RouterComponent class.
It would be best to decorate your class as Injectable and inject the value at the Angular component. e.g.
import { Injectable } from '#angular/core';
import { Router } from '#angular/router';
#Injectable()
export class RouterService {
constructor(private router: Router) { }
homePage(){
this.router.navigateByUrl('/home');
}
};
Register it in your module or add as dependency to the providers field in the Component decorator and import it into your components.
import { Component } from '#angular/core';
import { RouterService } from '...';
#Component({ ... })
export class LoginComponent {
constructor(private router: RouterService) { }
toHomePage() {
this.router.homePage();
}
};
Because it is an Injectable, Angular knows how to resolve the parameters.
The choice of namingconvention for your RouterComponent class would led others to think it is decorated as an Angular component, but you are using it as a service.

Angular2 Error inline template:1:20 caused by: Maximum call stack size exceeded

first of all let me start by saying I'm fully aware that there are a few similar posts related to this console error.
Normally I would refer to those but I have been using Angular2 from scratch for a total of 5 days and this is the first JS framework that I have ever used so trying to relate my problem to another is proving more difficult. Please bear than in mind before tearing me to shreds!
Now moving on to my problem, I have managed to cobble together a very basic scaffold for a site and I've created several components that I'm basically treating as each "page" of the site (in this case, 'home', 'contact', 'navbar', 'footer'). I have started to try and implement routing so that when the URL = '' you get redirected home, or if you put a specific in, it directs you accordingly.
The problem I'm getting is as soon as the site loads I get this console error: "Error: Error in ./HomeComponent class HomeComponent - inline template:1:20 caused by: Maximum call stack size exceeded".
My search so far has told me that somewhere I've got a recurring function, I tried to eliminate the variables (so far all of my classes contain almost 0 code) but I'm still getting this error.
Here is my app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { AppComponent } from './app.component';
import {HomeComponent} from './home/home.component';
import {ContactComponent} from './contact/contact.component';
// import {ProjectListComponent} from './projectlist/projectlist.component';
// import {ProjectDetailComponent} from './projectdetail/projectdetail.component';
// import {ProjectComponent} from './project/project.component';
import {NavbarComponent} from './navbar/navbar.component';
import {FooterComponent} from './footer/footer.component';
const appRoutes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'contact', component: ContactComponent },
// { path: 'project/:id', component: ProjectDetailComponent },
// {
// path: 'projects',
// component: ProjectListComponent,
// data: { title: 'Projects List' }
// },
{ path: '',
redirectTo: '/home',
pathMatch: 'full'
},
// { path: '**', component: PageNotFoundComponent }
];
#NgModule({
declarations: [
AppComponent,
HomeComponent,
ContactComponent,
// ProjectListComponent,
// ProjectDetailComponent,
// ProjectComponent,
NavbarComponent,
FooterComponent
],
imports: [
RouterModule.forRoot(appRoutes),
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component } from '#angular/core';
import {HomeComponent} from './home/home.component';
import {ContactComponent} from './contact/contact.component';
// import {ProjectListComponent} from './projectlist/projectlist.component';
// import {ProjectDetailComponent} from './projectdetail/projectdetail.component';
// import {ProjectComponent} from './project/project.component';
import {NavbarComponent} from './navbar/navbar.component';
import {FooterComponent} from './footer/footer.component';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.less']
})
export class AppComponent {
}
home.component.ts
import {Component} from '#angular/core';
import {HomeService} from './home.service';
#Component({
selector: 'home',
templateUrl: './home.component.html',
providers: [HomeService]
})
export class HomeComponent {
private title;
constructor(homeService: HomeService) {
this.title = homeService.getContent();
}
}
I'm not sure if you need my HTML but here is app.component.html
<navigation></navigation>
<router-outlet></router-outlet>
<footer class="footer"></footer>
and home.component.html (like I said it's basic at the moment)
<home>
<h1>{{title}}</h1>
</home>
I'm pretty baffled so far, I realise there is alot to take in and I'm trying to follow a couple of online courses (it's not being made easy by the changes from beta, most courses seem to be quite old at the moment).
Anyway I really do appreciate any help you can offer me and I most definitely appreciate you taking the time to help this noob be a little less noob.
The problem is that your home.component.html has a <home> tag in it. This cause it to infinitely create new home components which results in your maximum call stack size exceeded error.
Angular is trying to render something like:
<home>
<home>
<home>
...
</home>
</home>
</home>

Hash Location Strategy in Angular 2

I'm trying to create an application with hash location strategy, but it does not add the hash to the url. For instance when I click on a button associated with { path: '/polls', name: 'Polls', component: PollsComponent } it loads the page with this url : localhost:3000/polls.
What do I have to change to get the hash location strategy?
Why do I have to set the default base url if I want to use hash location strategy?
This is the routing in the app.component.ts where all the routing is defined:
import {Component} from 'angular2/core'
import {HTTP_PROVIDERS, Http} from 'angular2/http';
import 'rxjs/Rx'; // load the full rxjs
import {ROUTER_PROVIDERS, RouteConfig , ROUTER_DIRECTIVES} from 'angular2/router';
import { ResultsComponent } from './results/results.component'
import { VotingCardsComponent } from './votingcards/votingcards.component'
import { DashBoardComponent } from './dash/dash.component'
import { PollsComponent } from './pollslist/pollslist.component'
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [ROUTER_DIRECTIVES, ResultsComponent, VotingCardsComponent, DashBoardComponent],
providers: [HTTP_PROVIDERS,
ROUTER_PROVIDERS]
})
#RouteConfig([
{ path: '/vote', name: 'VotePage', component: VotingCardsComponent },
{ path: '/votepoll/:id', name: 'VotePoll', component: VotingCardsComponent },
{ path: '/results', name: 'Results', component: ResultsComponent },
{ path: '/polls', name: 'Polls', component: PollsComponent },
{ path: '/', name: 'DashBoard', component: DashBoardComponent, useAsDefault: true }
])
export class AppComponent { }
And this is my main.ts where I configure the base url:
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
//this is to avoid the href empty issue
import {provide} from 'angular2/core';
import {APP_BASE_HREF, ROUTER_PROVIDERS} from 'angular2/router';
bootstrap(AppComponent, [
//this is to avoid the href empty issue
ROUTER_PROVIDERS,
provide(LocationStrategy, { useClass: HashLocationStrategy }),
provide(APP_BASE_HREF, { useValue: '/' })
]);
You can use the option "useHash" in RouterModule.forRoot().
RouterModule.forRoot(appRoutes, {useHash: true});
https://discuss.atom.io/t/angular-2-routes-breaking-on-electron-app-refresh/28370/4
ROUTER_PROVIDERS should not be added to child components,
only to
providers: [ROUTER_PROVIDERS]
or alternatively only to
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
HTTP_PROVIDERS are in my opinion also a better fit for root component or bootstrap() but it doesn't break anything to add them somewhere else.
(See also Routing error with angular 2 and IIS)
Everything worked fine with the sample code OP posted as with what is in the accepted answer. But as a minor note, the format required to changing the Hash Location Strategy in the bootstrap file as of RC.4 goes like this:
{ provide: LocationStrategy, useClass: HashLocationStrategy },
It is recommended to use the HTML 5 style (PathLocationStrategy) as location strategy in Angular
Because
It produces the clean and SEO Friendly URLs that are easier for users
to understand and remember.
You can take advantage of the server-side rendering, which will make
our application load faster, by rendering the pages in the server
first before delivering it the client.
Use Hashlocationstrtegy only if you have to support the older
browsers.
Click Here for More info

Categories

Resources