Router unable to find component - angular6

I have defined a route in app-routing.module.ts
//question-details;question-id=a5551f5d-e8c6-4b1a-a7e2-6c878de291c7
{
path:'question-details;question-id=:id',
component:QuestionDetailsComponent
}
#NgModule({
imports:[RouterModule.forRoot(routes)], //
exports: [RouterModule],
providers:[]
})
export class AppRoutingModule{}
The route should get activated when an html button is clicked.
<button [routerLink]="[questionDetailRouterLink,{'question-id':question['question-id']}]" id="{{'show-more-button-'+(i+1)}}" class="btn content-div__button--blue btn-sm">Show more</button>
questionDetailRouterLink is defined as
export var QUESTION_DETAIL_ROUTER_LINK = '/question-details';
questionDetailRouterLink = QUESTION_DETAIL_ROUTER_LINK
When the button is clicked, the url in the browser changes to localhost:9000/question-details;question-id=a5551f5d-e8c6-4b1a-a7e2-6c878de291c7
But QuestionDetailsComponent is not shown. What am I doing wrong?
The RouterModule is defined as
app.module.ts
imports: [
AppRoutingModule,
...
]

In angular 6,Try this code ..
In html part:
<a [routerLink]="['/question-details/question-id']" mat-icon-button color="primary" [queryParams]="{question-id: id}">click here</a>
in Routing ts:
{
path:'question-details/question-id',
component:QuestionDetailsComponent
}

You can use the following in HTML
<button class="btn btn-info" [routerLink]="['/question-details']" [queryParams]="{question-id:id}">Show More</button>
In routing module
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { QuestionDetailsComponent } from 'ComponentPath';
const routes: Routes = [
{ path: 'question-details', component:QuestionDetailsComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

It seems I can't use query params (denoted by ?) or path parameters (denoted by ;) to specify a full route i.e. I can't do the following as then the route is not able to find the component
path:'question-details?question-id=:id', //question-details?question-id=a5551f5d-e8c6-4b1a-a7e2-6c878de291c7 - qusetion id is a query parameter
path:'question-details;question-id=:id', //question-details;question-id=a5551f5d-e8c6-4b1a-a7e2-6c878de291c7 - question id is a path parameter
I had to keep the route only till question-details and then extract query or path parameters(whatever I am using) in the component
{
path:'question-details',
component:QuestionDetailsComponent
}
I am passing the question-id as path param in html - <button [routerLink]="[questionDetailRouterLink, {'question-id':question['question-id']}]" id="{{'show-more-button-'+(i+1)}}" class="btn content-div__button--blue btn-sm">Show more</button>
and in the component, got the path params by calling this.question_id = this.route.snapshot.paramMap.get("question-id");//question-details;question-id=:id'
In summary, I can pass additional data to a route either as path parameter or query parameter but I can't use that to match/resolve a route. These parameters could be accessed in the component by calling respective properties.
Eg. passing both path parameter and query parameter to a routerlink
<button [routerLink]="[questionDetailRouterLink, {'question-id':question['question-id']}]" [queryParams]="{'query1':'value1'}" id="{{'show-more-button-'+(i+1)}}" class="btn content-div__button--blue btn-sm">Show more</button>
accessing them in the respective component
console.log("path params are :"+this.route.snapshot.paramMap);
console.log("query params are :"+this.route.snapshot.queryParamMap);
But route path is still
{
path:'question-details',
component:QuestionDetailsComponent
}
the above will print the following
path params are :
ParamsAsMap {params: {…}}
keys: (...)
params: {question-id: "a5551f5d-e8c6-4b1a-a7e2-6c878de291c7"}
__proto__: Object
question-details.component.ts:96 query params are :
ParamsAsMap {params: {…}}
keys: (...)
params: {query1: "value1"}
__proto__: Object
Which left me with question what does id mean in path: 'hero/:id'. It seems id would have the value between hero/ and the first ; or ? in the route. If the route is hero/my-hero/42?name=Manu or hero/my-hero/42;name=Manu or hero/my-hero/42;age=40?name=Manu then id in all the three would be my-hero/42 and the route will match any route which is hero/<something here> (not sure about this though)
this is a brilliant article about URLs - https://skorks.com/2010/05/what-every-developer-should-know-about-urls/

Related

How to get a specific data using id in Angular 6

I am trying to fetch a specific customer detail by clicking on a customer id or name, I have made name as a link so that when clicking it will route to a next page with id as a parameter,and display all the details of the specific customer, so can anyone suggest me a easy way to perform this in angular 6 . (link about a demo project will be helpful)
Am assuming many things here but what I understood is you have two different pages - one where you have the customer with an id and based on that id you want to navigate to a different page which contains the customer details.
Let`s say it is customer component. so, HTML would have some button or a link which will be like:
<button type="button" class="btn btn-info desc" (click)="openCard(card._id)">Open</button>
In your customer component you will have an event listener:
public openCard(_id: string) {
this.router.navigate(['/detail', _id]);
}
You will have a routing module which will be responsible for different routings taking place:
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: CardComponent },
{ path: 'detail', component: CardDetailComponent },
{ path: 'detail/:details', component: CardDetailComponent },
];
#NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
The last line inside the path is responsible for handling the id part which will be utilized to do the necessary logic inside the customer detail component. This routing module should be imported in your app module.
In the customer detail component.
ngOnInit() {
this.route.params.forEach((params: Params) => {
this.fetchDataService.getData().subscribe( data => {
this.cards = [...data];
this.cardDetails = this.cards.find(card => card._id === params.details);
})
});
}
And then inside card detail template:
<div class="card" *ngIf="cardDetails">
<img class="card-img-top" src="../assets/avatar.png" alt="{{cardDetails.title}}">
<div class="card-body">
<h5 class="card-title">{{cardDetails.title}}</h5>
<p class="card-text">{{cardDetails.description}}</p>
</div>
</div>
You can have a look at this repo which I created some time back if you want more details: GitHub Angular 5 Seed Master
Though this is in angular 5. The code will not be very different for Angular 6.
This also contains using a service to fetch data from mock json.
selectedHero: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
(use above code in component .ts file(on select))
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div>
<span>id: </span>{{selectedHero.id}}
</div>
<div>
<label>name:
<input [(ngModel)]="selectedHero.name" placeholder="name">
</label>
</div>
(use above code in component.html file(selected hero details))

How do I replace entire html with another html (Angular 2)

app.component.ts
<div>
<app-head></app-head>
<app-body></app-body>
</div>
head.component.ts
...
#Component({
selector: 'app-head',
templateUrl: './head.component.html',
styleUrls: ['./head.component.scss'],
providers: []
})
...
body.component.ts
...
#Component({
selector: 'app-body',
templateUrl: './body.component.html',
styleUrls: ['./body.component.scss'],
providers: []
})
...
So the pages loads with content head + body but now I wanted to route to a different page and replace entire existing page with the new page. How do I do that?
In my app.module.ts I have the following...
const routes: Routes = [
{ path: 'newPage', component: NewComponent}
]
I wanted use when clicked a button to be redirected to this page and replace existing <app-head> and <app-body> is this possible?
If I just use below I still see the current <app-head> and <app-body>
<button type="button" (click)="loadNewPage()" >
body.component.ts
loadNewPage() {
this.router.navigate(['/newPage']);
}
The results give me the current page.... and doesnt really apply since I am not concating the contents together. I want to replace the head.html and body.html with newpage.html from the NewComponent.ts
You need to replace the content in AppComponent with a router-outlet component and move that replaced content to a new component such as HomeComponent. Use the HomeComponent in your default route so it will load when you initially visit the site.
It's probably best if you check the documentation for Routing & Navigation since this is a pretty fundamental topic in Angular and there are a lot of details you should learn before you get too far.
App.component.html
<router-outlet></router-outlet>
home.component.html
<div>
<app-head></app-head>
<app-body></app-body>
</div>
app-routing.module.ts
const routes: Routes = [
{ path: '', component: HomeComponent }
{ path: 'newPage', component: NewComponent}
]
You will want to put a <router-outlet></router-outlet> in your app component and move what's in your current app component to a new component. Then update your routes to:
const routes: Routes = [
{ path: '', component: TheStuffYouMovedComponent },
{ path: 'newPage', component: NewComponent }
]

Angular router link to element with a specified id within the page

I'm using Angular Router and I'm trying to link to a sub-component in another route by id. Basically what would usually be done using the <a href="www.url.com/profile/#profile-header-id">.
I'm not sure if there's a built-in way for the Angular router to do this, but if not perhaps I can manually trigger the link at a later point when I know the element has been rendered.
The issue isn't linking to another route which of course is done with the Link from the Angular router. The issue is linking to an element which is found in the rendered HTML of the linked component.
Less Abstract Code Example:
So let's say my router in the app.module.ts file is
`const routes = [
{ path: '', component: HomeComponent},
{ path: '#section3', component: HomeSection3Component},
{ path: 'B', component: BComponent},
];`
Now in component OtherComponent, I want a Link that not only takes me to the home page route ' ', but also scrolls to the element of id #section3, thereby skipping all the irrelevant stuff.
My home component has nested components for each one of the sections of the page. Each section/component has an id.
home.component.html
`<main>
<app-section1></app-section1>
<app-section2></app-section2>
<app-section3></app-section3>
</main>`
However, all I can see is a blank page when clicking the button <button routerLink="#section3">Go to homepage section 3</button> on the B page.
The most elegant solution is just to add a fragment property to add the #section3 to the URL and then make it jump to this section with an anchor tag.
<div [routerLink]="['']" fragment="section3">
Jump to 'Section3' anchor
</div>
Use the routerLink directive combined with its fragment input property.
<a routerLink fragment="section3">Section 3</a>
With your routes, the rendered DOM is
Section 3
Make sure that you have imported RouterModule in the declaring module of the component in which you use the routerLink directive. Example:
import { CommonModule } from '#angular/common';
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
#NgModule({
declarations: [
HomeComponent,
HomeSection1Component
HomeSection2Component,
HomeSection3Component,
],
imports: [
CommonModule,
RouterModule,
],
})
export class HomeModule {}

Why is my application reloading the full page instead of the component when having an external routing file in angular 4?

I just started migrating an app to Angular + Flex-Layout + Angular Material.
I decided to have my routing in an external file called "app-routing.module.ts". I export my module in in the app.module.ts within "imports". This is my routing file:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { HomeComponent } from './home/home.component'
import { CreateMatchComponent } from './match/create-match.component'
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'match/new', component: CreateMatchComponent}
];
#NgModule({
imports: [ RouterModule.forRoot(routes)],
exports: [ RouterModule ]
})
export class AppRoutingModule {}
And here is the HTML from the app.component that renders my router outlet.
<div class="containerX">
<div fxLayout="row wrap">
<mat-toolbar color="primary" class="mat-elevation-z4">
<span>Amazing Football Stats App</span>
<span class="example-spacer"></span>
<mat-icon class="example-icon">favorite</mat-icon>
<mat-icon class="example-icon">delete</mat-icon>
</mat-toolbar>
</div>
<div fxLayout="row wrap" style="padding-top: 8px">
<router-outlet></router-outlet>
</div>
</div>
As you can see, my App Component has a div with the navigation bar and then another div with my <router-outlet>.
If I go to localhost:4200 it loads <app-root> which contains the <nav-bar> and the <router-outlet> and since the "route" is empty it redirects me to "/home".
Now my problem is this: If I change the URL to: localhost:4200/match/new (In the browser, in the URL bar) hit enter, I would expect to leave the <nav-bar> and only update the <router-outlet> and the same goes backwards.
If I am on a different page and I change the URL to "/home" (or even leaving it empty) it should keep the nav bar and only update the router outlet.
Sorry if this is a stupid question I just started with angular routing. What am I doing wrong?
When you change the browser location, the browser is handling that change and will send a new HTTP request to your server. That's why it reloads the whole page.
In order to only change the component loaded in the <router-outlet>, you need Angular's router to handle the change, which is done by using the routerLink directive:
<a routerLink="match/new" routerLinkActive="active">Create Match</a>
or programmatically with a call to router.navigate:
constructor(private router: Router) {}
...
goToCreateMatch() {
this.router.navigate(['/match/new']);
}
Here's a link to angular's documentation, for more info:
https://angular.io/guide/router#router-links
https://angular.io/api/router/Router#navigate

Angular does not recognise a selector within Template even if it has been declared in Component

I can't work out why Angular will not allow me to reference my components selector. I have a page which when you click on a list item the page should bring up another templates html. This is my code.
The error I keep receiving is 'message-component' is not a known element:
1. If 'message-component' is an Angular component, then verify that it is part of this module.
2. If 'message-component' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
Messages.component.html
<div id="Case" class="w3-container city" style="display:none">
<h2>Case</h2>
<message-case> </message-case>
</div>
I don't understand why it is giving me this error when the Message Component is declared and imported in both the NgModule and within the component.
Messages.Module.ts
#NgModule
({
imports: [SharedModule],
declarations: [
MessagesComponent,
MessageCaseComponent,
MessagesFilterPipe,
CreateMessageComponent,
],
})
Finally this is the file I am trying to display using the components selector
import { Component, OnInit } from '#angular/core';
import { IMessage } from './message';
import { ActivatedRoute, Router, Params } from '#angular/router';
import {MessagesComponent} from './messages.component';
import {CreateMessageComponent} from './createmessage.component';
#Component
({
moduleId: module.id,
selector: 'message-case',
templateUrl: 'message-case.html'
})
All help would be appreciated! I'm seemingly at a dead end right now.
Firstable the name file is wrong you putted this filename in the description
"Messages.component.html"
And the path of the template must contains "./" if it is in the same folder if it is in another folder you must put the relative path folder/file
#Component
({
moduleId: module.id,
selector: 'message-case',
templateUrl: './Messages.component.html'
})