How to get a specific data using id in Angular 6 - html

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))

Related

Router unable to find component

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/

Angular: Route from Card to a new View

I am working on an exercise project in Angular (latest V).
My App instanciates bootstrap cards dynamically from an Order Array and show them on my "Order-Item-Component through my template.
I added Routing so that I can update my OrderId on the Browser-Link after a click. It is working.
What I want is: If a user clicks on one of my cards - a whole new View Opens with my Order-Detail-Component for that specific Id. My cards should be invisible in that view. Subsequently, the user can go back to the cards-view with 'back' Link.
I don't know how to route so that my cards are going to be replaced by the Detail View.
Where do I have to place my 'router-outlet' for the detail-comp? I know, that I cannot place it in the same View as my Order-Component - because there are both visible in this case.
Here is my app.routing.ts: (The first route for orders is working fine)
import {RouterModule, Routes} from '#angular/router';
import {OrderComponent} from './order/order.component';
import {ORDER_ROUTES} from './order/order.routes';
import {OrderDetailComponent} from './order/order-detail/order-detail.component';
const APP_ROUTES: Routes = [
{ path: '', redirectTo: '/orders', pathMatch: 'full'},
{ path: 'orders', component: OrderComponent},
{ path: 'orders/:id', component: OrderDetailComponent
];
export const routing = RouterModule.forRoot(APP_ROUTES);
Here is my Order.Component.html:
<div class="container-fluid"><br>
<h2 id="heading-order"><i class="fa fa-shopping-cart f-left "></i>Open Orders</h2>
<p id="heading-items"> {{ orders.length }} Items </p>
</div>
<app-order-list></app-order-list>
<app-order-completed></app-order-completed>
Thanks in advance.
You might be able structure your app this way:
app.component.html:
<router-outlet></router-outlet>
routing module:
const APP_ROUTES: Routes = [
{ path: '', redirectTo: '/orders', pathMatch: 'full'},
{ path: 'orders', component: OrderComponent},
{ path: 'order-details/:id' component: OrderDetailsComponent}
];
order.component.html:
Provide [routerLink]="['/order-details', id] on your card, and pass the parameters to identify cards
Order component can also include <order-completed> in the view, if you need the completed orders to behave the same way, have them link to order details in the same way as the other orders.
To navigate back to the list of order, in your order-details.component.html provide a router link like routerLink="/orders"
You would use <router-outlet> instead of the custom tags <app-order-list></app-order-list>, <app-order-completed></app-order-completed> in your app component.
This way you can create child views:
const APP_ROUTES: Routes = [
{ path: '',
pathMatch: 'full',
component: OrderComponent,
children: [
{ path: 'order-list', component: OrderListComponent},
{ path: 'orders-completed', component: OrderCompletedComponent},
]},
];
And this is how the OrderComponent would look like:
<div class="container-fluid"><br>
<h2 id="heading-order"><i class="fa fa-shopping-cart f-left "></i>Open Orders</h2>
<p id="heading-items"> {{ orders.length }} Items </p>
</div>
<router-outlet></router-outlet>
Then use routerLink="/orders-completed" on a <button> or <a> tag to navigate

Why in my Angular-project does not replace home-page when I go to another route, and just adds the bottom of the page?

Here is the markup of my home page. I wrote several routes, and I need to display the content of the corresponding component instead of the home page when switching to them. And I have it added from the bottom of the home, and the home content continues to be displayed.
<div class="container">
<div class="row">
<app-header></app-header>
</div>
<div class="row">
<app-home></app-home>
<router-outlet></router-outlet>
</div>
<div class="row">
<app-footer></app-footer>
</div>
</div>
This is my app-home:
<app-home-news [homeImages]="homeImages"></app-home-news>
<router-outlet></router-outlet>
This is my routes:
const routes: Routes = [
{ path: 'sign-up', component: SignUpComponent },
{ path: 'sign-in', component: SignInComponent }
];
There is no error, the content simply adds to the home. How to make it appear in his place?
See anything which is outside <router-outlet></router-outlet> will always be there. Like in your case header and footer only should be in main html not home component. Anything you to change on the basis of routing, you should be part of routing configuration.
Make the following changes
<div class="container">
<div class="row">
<app-header></app-header>
</div>
<div class="row">
<!-- removed the home component -->
<router-outlet></router-outlet>
</div>
<div class="row">
<app-footer></app-footer>
</div>
</div>
Add the home component as the part of the routing.
const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'sign-up', component: SignUpComponent },
{ path: 'sign-in', component: SignInComponent }
];
Note : I add the component at the root level so I left the path blank but you can as per your path like
{ path: 'home', component: HomeComponent },
You need to be careful about your routes and what router outlets your urls are going to populate. It's not just a case of putting a router-outlet at the bottom of each of your components to display something new...
Assuming I had a very basic AppComponent template:
<h1>Hello</h1>
<router-outlet></router-outlet>
... and some configured routes:
{ path: '', component: HomeComponent }
{ path: 'test', component: TestComponent },
{ path: 'hello', component: HelloComponent}
... which just contained their own names in a p tag (home, test, and hello respectively).
The following would be true for each url:
example.com
Hello
Home
example.com/test
Hello
Test
example.com/hello
Hello
Hello
The route has loaded the component into the router-outlet.
If my components then had router outlets of their own, we're in to child route territory, wherein you start to use urls such as example.com/test/abc, with your routes looking more like:
{
path: 'test',
component: TestComponent,
children: [
{ path: 'abc', component: AbcComponent },
{ path: 'def', component: DefComponent }
]
}
Which would result - assuming the same content rules as above would look like:
example.com/test/abc:
Hello
Test
Abc
example.com/test/def:
Hello
Test
Def
Typically, your AppComponent handles your site-wide header/footer/nav/etc. with a single router-outlet that every other component will be loaded into, which includes your home page itself...
{ path: '', component: HomeComponent }
{ path: 'sign-up', component: SignupComponent }
{ path: 'sign-in', component: SigninComponent }
There may well be further router-outlets in the components (as above), but it seems that what you currently WANT, most likely, is this case rather than the more complex type with nested outlets above that you currently HAVE.

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

How to trigger multiple outlets with one routerLink in angular2 (2.1.1)

I'd like to swap out components in 2 separate areas of the DOM when I select a routerLink element. How can I route a single routerLink to 2 <router-outlet>s and designate a unique component for each <router-outlet>?
I'd like something like this:
<div id="region1>
<a routerLink="/view1" routerLinkActive="active">View 1</a>
<a routerLink="/view2" routerLinkActive="active">View 2</a>
<!-- First area to swap -->
<router-outlet name="sidebar"></router-outlet>
<div>
<div id="region2>
<!-- Second area to swap -->
<router-outlet name="mainArea"></router-outlet>
<div>
routes
const routes: Routes = [
{ path: '', redirectTo: 'view1', pathMatch: 'full'},
{ path: 'view1', {
outlets :
[
//one path specifies 2 components directed at 2 `router-outlets`
component: View1Sidebar, outlet : 'sidebar'
component: View1mainArea, outlet : 'mainArea'
]
}
},
{ path: 'view2', {
outlets :
[
component: View2Sidebar, outlet : 'sidebar'
component: View2mainArea, outlet : 'mainArea'
]
}
},
];
This cannot be done exactly as you ask. The purpose of a router is to maintain information about the specific page.
If you want to show and hide any components without reflecting any route information then you'll want to use the *ngIf directive. To use it like this, you'll need to keep a variable in you application somewhere that can be used to trigger the *ngIf directive.
You can make use any type of data, but you need to pass it to the *ngIf statement in the form of a boolean or expression that resolves to a boolean: here are examples"
component
showComponentBool: boolean = true;
showComponentStr: string = 'show';
html
<div *ngIf="showComponentBool">
<div *ngIf="showComponentStr='show'"></div>
</div>
With "#angular/core": "^4.0.0"
<a [routerLink]="[{ outlets: { primary: 'contact', aux: 'aside' }}]">Contact + Aux</a>
https://stackoverflow.com/a/42558766/2536623