What am I missing so I can use the router on Nativescript? - angular2-routing

I am attempting to build my first ever app using nativescript. I am going through the docs but not sure what I'm missing so I can't fix it.
I have the following structure:
- app
-- app-routing.module.ts
-- app.component.html
-- app.component.ts
-- app.css
-- app.module.ts
- home
-- home.component.css
-- home.component.html
-- home.component.ts
- restaurant
-- restaurant.component.css
-- restaurant.component.html
-- restaurant.component.ts
The thing is, I am trying to make it so that when someone taps on an element in the home.component.html:
<Image class="h3 m-5" col="0" row="0" src="~/images/beet-logo.jpg" (tap)="visitRestaurant()" height="87" width="80"></Image>
They are redirected to the restaurant.component.html page.
I defined the tap event as shown up there and then I have on my home.component.ts the following:
import { Router } from "#angular/router";
import { Component, OnInit } from "#angular/core";
#Component({
selector: "Home",
moduleId: module.id,
templateUrl: "./home.component.html",
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private router: Router) {
}
visitRestaurant() {
this.router.navigate(["/restaurant"]);
}
ngOnInit(): void {
}
}
When I click it, it fails though with the error:
ERROR Error: Uncaught (in promise): Error: Cannot match any routes.
URL Segment: 'restaurant'
I thought about adding the route here and also into app-routing.module.ts but whenever I try I get cannot find name: RestaurantComponent. So I assume I need to export the component somewhere but not sure where or how.
Can you guys help me?
This is my app-routing-module.ts in case it's useful:
import { NgModule } from "#angular/core";
import { Routes } from "#angular/router";
import { NativeScriptRouterModule } from "nativescript-angular/router";
const routes: Routes = [
{ path: "", redirectTo: "/home", pathMatch: "full" },
{ path: "home", loadChildren: "./home/home.module#HomeModule" }
];
#NgModule({
imports: [NativeScriptRouterModule.forRoot(routes)],
exports: [NativeScriptRouterModule]
})
export class AppRoutingModule { }
Here's my restaurant.component.ts code:
import { Router } from "#angular/router";
import { Component, OnInit } from "#angular/core";
#Component({
selector: "Restaurant",
moduleId: module.id,
templateUrl: "./restaurant.component.html",
styleUrls: ['./restaurant.component.css']
})
export class RestaurantComponent implements OnInit {
constructor(private router: Router) {
}
ngOnInit(): void {
}
}

You need to add a route for /restaurant. For example, you might do:
const routes: Routes = [
{ path: "", redirectTo: "/home", pathMatch: "full" },
{ path: "home", loadChildren: "./home/home.module#HomeModule" },
{ path: "restaurant", component: RestaurantComponent }
];
Additionally, you'll want to make sure your export/import statements appear appropriately.
Within restaurant.component.ts:
#Component({ ... })
export class RestaurantComponent { ... }
Within app-routing.module.ts:
import { RestaurantComponent } from ' ... ';

Related

Routing through links in Angular2

I am new in Angular 2 and I am still in learning phase, but I stuck in a problem and not getting the solution to it. Please help.
I have made a view of a login, then a link to it after clicking the link it will redirect to home then clicking a link there it will redirect to some other view.
Below is my code structure:
app.routing.ts:
import { Routes } from '#angular/router';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
import { UsersComponent } from './users/usercomponent';
export const routes: Routes = [
{ path: 'Home', component: HomeComponent },
{ path: 'Login', component: LoginComponent },
{ path: 'User', component: UsersComponent },
];
app.module.ts:
import { FormsModule } from '#angular/forms';
import { routes } from './app.routing';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
import { UsersComponent } from './users/usercomponent';
#NgModule({
imports: [BrowserModule, FormsModule, RouterModule.forRoot(routes)],
declarations: [AppComponent, LoginComponent, HomeComponent, UsersComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts:
import { Component } from '#angular/core';
import { OnInit } from '#angular/core';
#Component({
selector: 'app-initializer',
templateUrl: './app.component.html'
})
export class AppComponent {
title = 'Some NAme'
}
app.component.html:
<a routerLink="Login">Login</a>
<br />
<div>
<router-outlet></router-outlet>
</div>
login.component.ts:
import { Component } from '#angular/core';
#Component({
selector: 'login',
template: `
<h1><a routerLink="Home">Home</a>
<a routerLink="User">Users</a></h1>
<div>
<router-outlet></router-outlet>
</div>
`
})
export class LoginComponent {
constructor() {
}
}
The first page is working but after clicking home it is giving an error:
Cannot match any routes. URL Segment: 'Login/Home
I know that the link will be like / login, /home etc not like /login/home but how to implement it as I am not getting the solution for it and I am completely new to it.
Instead of giving only <h1><a routerLink="Home">Home</a>
you need to add / before the link like <h1><a routerLink="/Home">Home</a>.

How to write unit testing for router.url in angular 2

Please help to write unit testing on router.url usging angular 2. Please have a look at the below code to understand my query.
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-about',
templateUrl: './app-about.component.html',
styleUrls: ['./app-about.component.scss']
})
export class AboutComponent implements OnInit {
constructor(private router: Router) {
if (this.router.url.includes('home')) {
...some functions
}
}
}
In my unit test, I don't not try to modify "router.url" but I navigate to the wanted url.
To do this I use the Angular's RouterTestingModule:
TestBed.configureTestingModule({
declarations: [MyComponentToTest, DummyComponent],
providers: [Location],
imports: [RouterTestingModule.withRoutes([{ path: 'search', component: DummyComponent },
{ path: 'dashboard', component: DummyComponent }])]
}).compileComponents();
With Dummy component:
#Component({ template: '' })
class DummyComponent { }
It sets up the router with two mocked routes.
Then, in the test I recover the router:
const router = TestBed.get(Router);
And navigate to the wanted url:
router.navigate(['/search']);
You might need to do a fixture.detectChanges(); to refresh the component before any other actions.

Routing when nested components are used on AppComponent

I am fairly new to Angular 2 and having a problem with Routing. I have just started to explore the Routing. I will explain the structure and what I have achieved so far,
app.router.ts
import { ModuleWithProviders } from '#angular/core'
import { Routes, RouterModule } from '#angular/router'
import { AppComponent } from './app.component';
import { LoginComponent } from "../app/login/login.component"
export const router: Routes = [
{ path: '', component: LoginComponent },
{ path: 'login', component: LoginComponent },
{ path: 'dashboard', component: AppComponent }
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import {UiSwitchModule} from 'angular2-ui-switch'
import { AppComponent } from './app.component';
import { AllReportsComponent } from "../app/all-reports/all-reports.component"
import { AvailableReportsComponent } from "../app/available-reports/available-reports.component"
import { NextReportsComponent } from "../app/next-reports/next-reports.component"
import { UrlsComponent } from "../app/urls/urls.component"
import { LoginComponent } from "../app/login/login.component"
import { TaskApi } from "../app/api/TaskApi"
import { routes } from "../app/app.router"
#NgModule({
imports: [
BrowserModule,
FormsModule,
UiSwitchModule,
HttpModule,
routes
],
declarations: [
AppComponent,
AllReportsComponent,
AvailableReportsComponent,
NextReportsComponent,
UrlsComponent,
LoginComponent
],
bootstrap: [AppComponent]
})
export class AppModule {
}
app.html
<div>
<all-reports></all-reports>
<available-reports></available-reports>
<next-reports></next-reports>
<urls></urls>
</div>
app.component.ts (very simple)
import { Component } from "#angular/core"
#Component({
templateUrl: '../app/app.html'
})
export class AppComponent {
}
and login.component.ts
import { Component } from '#angular/core';
import { TaskApi } from '../api/TaskApi';
import * as models from '../model/models';
#Component({
styleUrls: ['/app/css/login.css'],
templateUrl: '../../app/login/login.html',
providers: [TaskApi]
})
export class LoginComponent {
}
Now it can be seen that I am using multiple directives on app.html and all the respective components are working fine.
The problem I am facing is when I introduce Routing then I am able to understand where to use "router-outlet". I have used it on Index.html but it does not work and gives error about ng-component. So to just test around I have used following in Index.html,
<body>
<base href="/">
<ng-component></ng-component>
</body>
After I do this then my AppComponent is displayed by default where the LoginComponent should be displayed by default. On console, It also gives me error "Error: Cannot find primary outlet to load 'LoginComponent'"
Kindly guide me if I am using 4 directives on App.html as mentioned above then in that case how the routing will work. To summarize, I want to display Login page on localhost:3009/login and localhost:3009 and I want to display Home page (app.html) in localhost:3009/dashboard and app.html is using 4 directives to display 4 child components on it.
Angular Routing
Since Angular is single page application the routing functionality
helps to display different view in single page.
How to use router to change view?
since app.component.html is main view for most user. Iam also consider app.component.html as main view.
Router-outlet
Router-outer helps to load the change in our angular application.
app.component.html
<router-outlet></router-outlet>
Set AppComponent Default page as router-outlet and create new Dashboard.component.html in your main view.
router.ts
import { ModuleWithProviders } from '#angular/core'
import { Routes, RouterModule } from '#angular/router'
import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard.component';
import { LoginComponent } from "../app/login/login.component"
export const router: Routes = [
{ path: '', component: LoginComponent },
{ path: 'login', redirectTo: '', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent }
];
export const routes: ModuleWithProviders = RouterModule.forRoot(router);
The problem with your code is that there is no 'router-outlet', so angular doesn't understand where to display the view.
The 'router-outlet' directive marks where the router displays a view.
In your code, since in app.component.ts you are using app.html so you should use <router-outlet> </router-outlet> in that HTML file.
Your app.html file should look like this:
<router-outlet> </router-outlet>
These below things should not be used in the app component HTML file. They should be used in their the corresponding components.
<all-reports></all-reports>
<available-reports></available-reports>
<next-reports></next-reports>
<urls></urls>
For further understanding, please refer to the official documentation of Angular2. They have explained it pretty well here https://angular.io/docs/ts/latest/guide/router.html

Adding Dragular to Angular2 Application: document is not defined

I am fairly new to Angular2 and I am having issues adding Dragula to my application. When I run the application an error is thrown prior to loading the home page:
Exception: Call to Node module failed with error: Prerendering failed because of error: ReferenceError: document is not defined
The error message mentions Prerending which I suspect is in relation to the project using asp-prerender-module.
I've tried to follow official tutorials from Dragula and forum posts. Below are my app.module and component file snippets (... denotes summarised code):
app.module.ts
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './components/app/app.component'
...
import { SearchComponent } from './components/search/search.component';
import { BrowserModule } from '#angular/platform-browser';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { Injectable } from '#angular/core';
import { DragulaModule } from 'ng2-dragula';
#NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
...
SearchComponent
],
imports: [
UniversalModule,
BrowserModule,
FormsModule,
DragulaModule,
CommonModule,
RouterModule.forRoot([
{ path: '', redirectTo: 'home', pathMatch: 'full' },
...
{ path: 'search', component: SearchComponent },
{ path: '**', redirectTo: 'home' }
])
]
})
export class AppModule {
}
search.component.ts
import { Component } from '#angular/core';
import { Http } from '#angular/http';
import { SearchService } from '../../services/search.service';
import { DragulaService } from 'ng2-dragula';
#Component({
selector: 'search',
template: require('./search.component.html'),
providers: [SearchService, DragulaService]
})
I suspect I am missing an a step when including Dragula, but I cannot figure out where. I have included both dragula (^3.7.2) and ng2-dragula (^1.3.0) in my package.json file.
your DragulaService initialization is wrong!! check Dragula documentation link
search.component.ts
import { Component } from '#angular/core';
import { Http } from '#angular/http';
import { SearchService } from '../../services/search.service';
import { DragulaService } from 'ng2-dragula';
#Component({
selector: 'search',
template: require('./search.component.html'),
providers: [SearchService]
})
expoert searchcomponent{
constructor(private dragulaService: DragulaService) {
console.log('DragulaService created');
}
}
Now you can play with drag and drop
If you want more control over drag and drop you can add events and options to dragulaService.
constructor(private dragulaService: DragulaService) {
dragulaService.drag.subscribe((value) => {
console.log(`drag: ${value[0]}`);
this.onDrag(value.slice(1));
});
dragulaService.drop.subscribe((value) => {
console.log(`drop: ${value[0]}`);
this.onDrop(value.slice(1));
});
dragulaService.over.subscribe((value) => {
console.log(`over: ${value[0]}`);
this.onOver(value.slice(1));
});
dragulaService.out.subscribe((value) => {
console.log(`out: ${value[0]}`);
this.onOut(value.slice(1));
});
}
private onDrag(args) {
let [e, el] = args;
// do something
}
private onDrop(args) {
let [e, el] = args;
// do something
}
private onOver(args) {
let [e, el, container] = args;
// do something
}
private onOut(args) {
let [e, el, container] = args;
// do something
}

Error while configuring routes in Angular 2

i have been working with a product list Project and while configuring routes to navigate between different views, I get a red squiggly under the '#Routes' decorator and when i hover over the Routes, it says 'Routes only refers to a type, but is being used as a value here'. I researched in so many sights including here and tried many different ways to resolve this but I could not find out the issue.
app.component.ts
import { Component } from '#angular/core';
import { ProductListComponent } from './products/product-list.Component';
import { ProductService } from './products/product.service'
import { Routes } from '#angular/router';
import 'rxjs/Rx'; // Load all features
import { WelcomeComponent } from './home/welcome.component'
#Component({
selector: 'pm-app',
template: `
<div>
<nav class='navbar navbar-default'>
<div class='container-fluid'>
<a class='navbar-brand'>{{pageTitle}}</a>
<ul class='nav navbar-nav'>
<li><a>Home</a></li>
<li><a>Product List</a></li>
</ul>
</div>
</nav>
</div>
` ,
entryComponents : [ProductListComponent],
providers: [ProductService]
})
#Routes([
{ path: '/welcome' , name: 'Welcome' , component: WelcomeComponent, useAsDefault: true},
{ path: '/products' , name: 'Products' , component: ProductListComponent }
])
export class AppComponent {
pageTitle:string = 'Acme Product Management';
}
app.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { ProductListComponent } from './products/product-list.Component';
import { HttpModule } from "#angular/http";
import { RouterModule } from '#angular/router'
import { ProductFilterPipe } from './products/product-filter.pipe';
import { StarComponent } from './shared/star.component';
import { AppComponent } from './app.component';
#NgModule({
imports: [ BrowserModule,FormsModule,HttpModule,RouterModule],
declarations: [ AppComponent,ProductListComponent,ProductFilterPipe,StarComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
welcome.compnent.ts
import { Component } from '#angular/core';
#Component({
templateUrl: 'app/home/welcome.component.html'
})
export class WelcomeComponent {
public pageTitle: string = 'Welcome';
}
I think my coding is fine. But unable to get the expected result. Please Help!
Found out, the issue is... with RC5, Routes is an array of path's & is no more a Decorator, and you have to import 'RouterModule' instead of 'provideRouter'. While exporting you have to use 'RouterModule.forRoot'.
Also with RC5, we no longer specify the string name of the component while configuring routes instead we only specify the path & component only. And we no longer use the prefix '/' for the path. Also we no longer using useAsDefault instead we use redirectTo property to configure the default path.
I have used a separate module to do my route configurations instead of doing it in the root component as earlier. An updated version of my route configuration is given as below. Hope this will be helpful.
app.routes.ts
import { Routes, RouterModule } from '#angular/router';
import { ProductListComponent } from './products/product-list.Component';
import { WelcomeComponent } from './home/welcome.component'
import { ProductDetailComponent } from './products/product- detail.component';
const routes: Routes = [
{
path: 'welcome' ,
component: WelcomeComponent,
},
{
path: 'products' ,
component: ProductListComponent
},
{
path: 'product/:id' ,
component: ProductDetailComponent
},
{
path:'',
redirectTo:'/welcome',
pathMatch:'full'
},
];
export const routing = RouterModule.forRoot(routes);

Resources