How to pass value(index) through navigateByUrl - html

I have created two components home where I will show minute details about a Employee, and view where I will show complete details about a Employee.
My home.component.html is as follows:
<header>Welcome Home</header>
<br>
<div class="container panel panel-default" *ngFor="let employee of employeeList;">
<div class="panel-heading">
<h3 class="panel-title">{{employee.firstName}} {{employee.lastName}}</h3>
</div>
<div class="panel-body">
<div class="col-xs-10">
<div class="row vertical-align">
<div class="col-xs-8 offset-md-2">
<div class="row">
<div class="col-xs-6">
First Name
</div>
<div class="col-xs-6">
{{employee.firstName}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Last Name
</div>
<div class="col-xs-6">
: {{employee.lastName}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Gender
</div>
<div class="col-xs-6">
: {{employee.gender}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Department
</div>
<div class="col-xs-6">
: {{employee.department}}
</div>
</div>
<div>
<button class="btn btn-primary" (click)="viewEmployee(employee.id)">
View
</button>
<button class="btn btn-primary" (click)="editEmployee(employee.id)">
Edit
</button>
</div>
</div>
</div>
</div>
</div>
</div>
My home.component.ts is as follows:
import { Component, NgModule, OnInit } from '#angular/core';
import { Router, RouterModule, Routes } from '#angular/router';
import employees from './../employeeDetails/employees.json';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private router: Router) {
}
public employeeList: {
id: number;
firstName: string;
lastName: string;
gender: string;
age: number;
email?: string;
phoneNumber?: number;
department: string;
}[] = employees;
ngOnInit(): void {
}
viewEmployee(id): any {
this.router.navigateByUrl('/view');
}
editEmployee(i): any {
this.router.navigateByUrl('/edit');
}
}
When I click on button available in home component, it has to carry the index or id of the employee. and show only specific details about that employee. Presently, when I click view button, it is displaying all the details of all employees.
My view.component.html is as follows:
<header>View Page</header>
<br>
<div class="container panel panel-default" *ngFor="let employee of employeeList;">
<div class="panel-heading">
<h3 class="panel-title">{{employee.firstName}} {{employee.lastName}}</h3>
</div>
<div class="panel-body">
<div class="col-xs-10">
<div class="row vertical-align">
<div class="col-xs-8 offset-md-2">
<div class="row">
<div class="col-xs-6">
First Name
</div>
<div class="col-xs-6">
: {{employee.firstName}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Last Name
</div>
<div class="col-xs-6">
: {{employee.lastName}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Gender
</div>
<div class="col-xs-6">
: {{employee.gender}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Age
</div>
<div class="col-xs-6">
: {{employee.age}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Email
</div>
<div class="col-xs-6">
: {{employee.email}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Phone Number
</div>
<div class="col-xs-6">
: {{employee.phoneNumber}}
</div>
</div>
<div class="row">
<div class="col-xs-6">
Department
</div>
<div class="col-xs-6">
: {{employee.department}}
</div>
</div>
<div>
<button class="btn btn-primary" (click)="editEmployee()">Edit</button>
</div>
</div>
</div>
</div>
</div>
</div>
My view.comonent.ts is as follows:
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import employees from './../employeeDetails/employees.json';
#Component({
selector: 'app-view',
templateUrl: './view.component.html',
styleUrls: ['./view.component.css']
})
export class ViewComponent implements OnInit {
constructor(private router: Router) { }
public employeeList: {
id: number;
firstName: string;
lastName: string;
gender: string;
age: number;
email?: string;
phoneNumber?: number;
department: string;
}[] = employees;
ngOnInit(): void {
}
editEmployee(): any {
this.router.navigateByUrl('/edit');
}
}
In total I have 3 employees, which I have specified in employee.json file. Which is as follows:
[
{
"id": 1,
"firstName": "Abhi",
"lastName": "A B",
"gender": "male",
"age": 25,
"email": "Abhi#gmail.com",
"phoneNumber": 8888888888,
"department": "IT"
},
{
"id": 1,
"firstName": "Amogh",
"lastName": "A M",
"gender": "male",
"age": 25,
"email": "Amogh#gmail.com",
"phoneNumber": 8888888888,
"department": "IT"
},
{
"id": 1,
"firstName": "Harsha",
"lastName": "H A",
"gender": "male",
"age": 25,
"email": "Harsha#gmail.com",
"phoneNumber": 8888888888,
"department": "IT"
}
]
Please help.

You may pass the id like this:
this.router.navigateByUrl(`/view/${id}`);
And then on the view component get it like this:
constructor(private router: Router, private route: ActivatedRoute) { }
///
ngOnInit() {
this.route.params.subscribe((params) => {
const employeeId = params.id;
});
}
This is a code sandbox that might help you: https://codesandbox.io/s/flamboyant-rubin-x2fuc?file=/src/app/view/view.component.ts
Important points:
The json file has id 1 for all employees, I changed this on the codesandbox for it to work well.
The view component html should not have an ngFor since you want only one employee on this view.
*ngFor="let employee of employeeList;
I removed this on the sandbox from the view.component.html
This is the core of the answer. Adds a local variable to store the employee and then assigns it filtering from the json using the id from params.
employee;
ngOnInit(): void {
this.route.params.subscribe((params) => {
const employeeId = params.id;
this.employee = employees.filter((e) => e.id === +employeeId)[0];
});
}

Just follow along with this video: link
it's explaining exactly what you want to achieve with angular router.
EDIT:
You can visit this demo too: link, and notive the relationship between hero-list component and hero-detail component, both of them inside heroes folder.
for example, in the demo app, if you click on heroes you navigate to hero-list component, and after that if you click on Dr Nice for example:
you navigate to hero-detail component, but with data corresponding to Dr Nice:

Related

Angular associate json value to img path

I have to display data that comes from an api that works well, I need to display each country with its corresponding flag but I don't understand how to associate the value of a json with the path of an image.
example : for the
libelle: Cambodge bigramme: KH
display: src/assets/flags/KH.jpg
libelle: France bigramme: FR
display: src/assets/flags/FR.jpg
I have tried to be as clear as possible.
thank you.
json
"drapeaux": [
{
"id": 1,
"mnemo": "KHM",
"libelle": "Cambodge",
"bigramme": "KH"
},
{
"id": 2,
"mnemo": "KHM",
"libelle": "France",
"bigramme": "FR"
}
]
}
service
getAll(): Observable<Ipost[]> {
return this.http.get<Ipost[]>(this.api);
}
components.ts
getAllNations() {
let resp = this.homeService.getAll();
resp.subscribe(result => {
this.postArray = result;
});
}
html
<div class="col-12">
<mat-card>
<div class="row">
<div class="col-1" *ngFor="let post of postArray">
{{post.libelle}}
<img [src]="post.bigramme.jpg" alt="flag">
</div>
</div>
</mat-card>
</div>
You have two options:
Option 1: In your service:
getAll(): Observable<Ipost[]> {
return this.http.get<Ipost[]>(this.api).pipe(
map(p => ({
...p,
bigramme: `src/assets/flags/${p.bigramme}.jpg`
}))
)
}
And then your Component's html:
<div class="col-12">
<mat-card>
<div class="row">
<div class="col-1" *ngFor="let post of postArray">
{{post.libelle}}
<img [src]="post.bigramme" alt="flag">
</div>
</div>
</mat-card>
</div>
Option 2: Or you can change only your Component's html:
<div class="col-12">
<mat-card>
<div class="row">
<div class="col-1" *ngFor="let post of postArray">
{{post.libelle}}
<img src="src/assets/flags/{{ post.bigramme }}.jpg" alt="flag">
</div>
</div>
</mat-card>
</div>

How to align texts dynamically in Grid tile container in Html in Angular

This is my parent component.
<div class="o-tile-container ">
<div *ngFor="let country of Countrys">
<app-country
[name]="name"
[count]="count"
[level]="'Country'"
></app-country>
</div>
</div>
This is my common country child component Html code
<div [matRippleColor]="primary" class="m-tile" matRipple>
<div class="a-tile-graph">
<div class="titles">
<div class="head" id="heading-name">{{name}}</div>
<div class="sub">{{level}}</div>
</div>
</div>
<div class="content-tile">
<div class="o-tile-content">
<div class="a-tile-title">{{name}}</div>
<div class="a-tile-count">{{count}}</div>
</div>
</div>
</div>
This kind of a thing.
In here i want to display heading-name in the same level of every tile and level country in a same level from top in every container. How can i do this?
To align text dynamically you can pass your style as #Input I have a sample code for you what exactly you want. Please check my code and demo code in stackblitz Demo LINK StackBlitz=>
** Parent HTML:**
<div class="o-tile-container ">
<div *ngFor="let country of Countrys">
<app-country
[name]="country.name"
[count]="country.count"
[level]="country.level"
[mystyle]="country.style"
></app-country>
</div>
</div>
Child HTML:
<div style="border-style: solid;width:100px" [matRippleColor]="primary" class="m-tile" matRipple [ngStyle]="this.mystyle">
<div class="a-tile-graph" >
<div class="titles">
<div class="head" id="heading-name" >{{name}} </div>
<div class="sub">{{level}}</div>
</div>
</div>
<div class="content-tile">
<div class="o-tile-content">
<div class="a-tile-title">{{name}}</div>
<div class="a-tile-count">{{count}}</div>
</div>
</div>
</div>
TS:
Parent TS:
export class AppComponent {
Countrys:any=[];
rippleColor: string = "white";
constructor(){
let c1=new Country();
c1.count=1;
c1.level='L1';
c1.name='A';
c1.style={'text-align':'center'}
this.Countrys.push(c1);
let c2=new Country();
c2.count=2;
c2.level='L2';
c2.name='B';
c2.style={'text-align':'right'};
this.Countrys.push(c2);
let c3=new Country();
c3.count=3;
c3.level='L3';
c3.name='C';
c3.style={'text-align':'left'};
this.Countrys.push(c3);
}
}
class Country{
name;string;
count:number;
level:string;
style:any;
}
Child TS:
export class CountryComponent implements OnInit {
#Input() level:string;
#Input() name:string;
#Input() count:number;
#Input() mystyle:any;
constructor() {
}
ngOnInit() {
}
}

How to add Row after every 3 columns in angular

What i am trying to do is add a row div after every 3 colum divs
Example Output need:
<div class="row">
<div class="col-md-6"></div>
<div class="col-md-6"></div>
<div class="col-md-6"></div>
</div>
I have an array of products i am iltrating like this
<div class="row" *ngFor="let p of relatedProperties;let i = index">
<div class="col-md-6" *ngIf="relatedProperties[i].title !== undefined">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i].title !== undefined">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i].title !== undefined">{{ relatedProperties[i].title }}</div>
</div>
But the problem is that my every row prints same title on one iltration and second on next iltration
Current output
<div class="row">
<div class="col-md-6">Title1</div>
<div class="col-md-6">Title1</div>
<div class="col-md-6">Title1</div>
</div>
<div class="row">
<div class="col-md-6">Title2</div>
<div class="col-md-6">Title2</div>
<div class="col-md-6">Title2</div>
</div>
<div class="row">
<div class="col-md-6">Title3</div>
<div class="col-md-6">Title3</div>
<div class="col-md-6">Title3</div>
</div>
Desired Output
<div class="row">
<div class="col-md-6">Title1</div>
<div class="col-md-6">Title2</div>
<div class="col-md-6">Title3</div>
</div>
<div class="row">
<div class="col-md-6">Title4</div>
<div class="col-md-6">Title5</div>
<div class="col-md-6">Title6</div>
</div>
<div class="row">
<div class="col-md-6">Title7</div>
<div class="col-md-6">Title8</div>
<div class="col-md-6">Title9</div>
</div>
If you split your Array into subarrays with always 3 titel's then you can easy loop through this Array in your template.
https://ng-run.com/edit/zZsztdvTOTpzbUC5Buuj?open=app%2Fapp.component.ts
component html
<div class="row" *ngFor="let row of newTitleArr; let i = index">
<div class="col" *ngFor="let col of newTitleArr[i]">{{ col.title }}</div>
</div>
component ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
titleArr = [
{ title: 'title1' },
{ title: 'title2' },
{ title: 'title3' },
{ title: 'title4' },
{ title: 'title5' },
{ title: 'title6' },
{ title: 'title7' },
{ title: 'title8' },
{ title: 'title9' },
{ title: 'title10' },
{ title: 'title11' },
{ title: 'title12' },
{ title: 'title13' },
];
newTitleArr:any[];
ngOnInit() {
this.newTitleArr = this.splitArr(this.titleArr, 3)
}
splitArr(arr, size) {
let newArr = [];
for(let i = 0; i< arr.length; i += size) {
newArr.push(arr.slice(i, i+size));
}
return newArr;
}
}
Maybe this works, but Im unsure
<ng-container *ngFor="let p of relatedProperties; let i = index">
<div class="row" *ngIf="(i + 1) / 3 === 1">
<div class="col-md-6" *ngIf="relatedProperties[i - 2].title != null">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i - 1].title != null">{{ relatedProperties[i].title }}</div>
<div class="col-md-6" *ngIf="relatedProperties[i].title != null">{{ relatedProperties[i].title }}</div>
</div>
</ng-container>
Also, I gotta say this feels pretty hacky, but if this is what you request, this should work
edit:
Note that strict null (a == null) is better than checking for undefined (a === undefined), as it will check for both undefined or null. In your case title != null.
Also, you could build an iterable that holds the structure you want in a cleaner way.
instead of having [title1, title2, title3, title4, title5, title6...] you should try to have [[title1, title2, title3], [title4, title5, title6], ...] which is way cleaner and allows you to simply have two *ngFors inside your template
<element1 *ngFor="let innerArray of myArray; let i = index">
<element2 *ngFor="let title of innerAray; let j = index">
</element2>
</element1>
And finally, I suggest you avoid calling a variable 'p', that's bad practice.
You can use this to add a row after every 3 columns.
<ng-container *ngFor="let p of relatedProperties; let i = index">
<div class="row" *ngIf="(i%3)==0">
<div class="col-md-6" *ngFor="let p of relatedProperties.slice(i, i+3)>
<span *ngIf="relatedProperties[i].title !== undefined"> {{ relatedProperties[i].title }} </span>
</div>
</div>
</ng-container>

How to select particular field in Angular 6

enter image description here
html code
<div id="myModal" class="modal">
<div class="modal-content">
<div class="modal-header" style="text-align: center;">
<span class="close">×</span>
<h2>Register Account</h2>
</div>
<div class="modal-body">
<div class="signup-body">
<div class="su-body" style="background-color:#3B5998;">
Employer
</div>
<div class="su-body" style="background-color:#3B5998;">
Candidate
</div>
</div>
<div class="signup-body">
<div class="su-body" style="background-color:#3B5998;">
Login with Faceboo
</div>
<div class="su-body" style="background-color:#3B5998;">
Login With Google
</div>
</div>
<div class="signup-body">
<div class="su-body" style="background-color:#3B5998;">
Login With Linkedin
</div>
<div class="su-body" style="background-color:#3B5998;">
Login With Twitter
</div>
</div>
</div>
<div class="modal-footer">
<div class="signup-body">
<!-- <button>Sign up</button> -->
<div class="su-body" style="background-color:#3B5998;">
Sign up
</div>
</div>
<p>Already have ab account</p>Login
</div>
</div>
</div>
I want to create a registration page has given below in angular 6. But my question is when user can register two ways (either employer or candidate ) so how can i send Api particular field data. please help me.
Please check below solution might be it can help you to observe Registration Type:
Registered Event in Html:
<div class="signup-body">
<div class="su-body" style="background-color:#3B5998;">
<a href="#" target="_blank" (onclick)="changeReg('Employer')" >Employer</a>
</div>
<div class="su-body" style="background-color:#3B5998;">
<a href="#" target="_blank" (onclick)="changeReg('Candidate')" >Candidate</a>
</div>
</div>
Create a data sharing service
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs';
#Injectable()
export class DataService {
private regSource = new BehaviorSubject('Employer'); //Default registration type
currentReg = this.regSource.asObservable();
constructor() { }
changeRegType(regTyp: string) {
this.regSource.next(regTyp)
}
}
Set New Registration type within Supplied Html component:
import { Component, OnInit } from '#angular/core';
import { DataService } from "../data.service";
#Component({
selector: 'app-registration',
styleUrls: ['./registration-selection.component.css']
})
export class RegistrationSelectionComponent implements OnInit {
constructor(private data: DataService) { }
changeReg(regType:String) {
this.data.changeRegType(regType);
}
}
Get default/new registration type in signup component:
import { Component, OnInit } from '#angular/core';
import { DataService } from "../data.service";
#Component({
selector: 'app-signup',
template: `
{{message}}
`,
styleUrls: ['./signup.component.css']
})
export class SignUpCmponent implements OnInit {
regType:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentReg.subscribe(reg => this.regType = reg)
}
}

Struggling to read in JSON file in Angular 2+ project

I have used the Angular CLI to set up this project so the standard folder layout holds. I am trying to practice reading in a JSON file from src/app/assets/items.json and use it to display these items in the html.
items.json:
{
"results": [
"Item 1",
"Item 2",
]
}
app.service.ts in src/app/:
import { Injectable } from '#angular/core';
import { Http, Response, Headers, RequestOptions } from '#angular/http';
import { Observable } from 'rxjs/Rx';
// Import RxJs required methods
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
#Injectable()
export class AppService {
private greetUrl = 'api/Hello';
// Resolve HTTP using the constructor
constructor(private _http: Http) { }
findJSON(): Observable<any> {
return this._http.get('assets/items.json').map((response: Response) => {
return response.json();
});
}
sayHello(): Observable<any> {
return this._http.get(this.greetUrl).map((response: Response) => {
return response.text();
});
}
}
and app.component.ts in src/app:
import { Component, OnInit } from '#angular/core';
import { Http, Response } from '#angular/http';
import { AppService } from './app.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
greetings = '';
itemsjson : string;
constructor(private _appService: AppService) { }
ngOnInit(): void {
this._appService.findJSON()
.subscribe(
result => {
this.itemsjson = result;
}
);
}
}
and app.component.html in src/app/:
<html lang="en">
<link rel="stylesheet" href="https://bootswatch.com/cerulean/bootstrap.min.css">
<head>
<meta charset="utf-8">
<title>Yik-Yak Clone</title>
</head>
<body>
<div class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
Yik-Yak Clone
</div>
</div>
</div>
<!-- Containers
================================================== -->
<div class = "container">
<div class="row">
<div class="col-lg-12">
<div class="bs-component">
<div class="jumbotron">
<h1>{{itemsjson}}</h1>
</div>
</div>
</div>
</div>
</div>
<!-- Containers
================================================== -->
<div class = "container">
<div class="row">
<div class="col-lg-12">
<div class="bs-component">
<div class="jumbotron">
<h1>{{itemsjson}}</h1>
</div>
</div>
</div>
</div>
</div>
<!--
================================================== -->
<div class = "container">
<div class="row">
<div class="col-lg-12">
<div class="bs-component">
<div class="jumbotron">
<h1>{{itemsjson}}</h1>
</div>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-default navbar-fixed-bottom">
<div class="container">
<div class="navbar-head">
<div class = "col-sm-3"></div>
<div class="col-sm-6">
<div class="form-group">
<input class="form-control input-lg" type="text" id="inputLarge">
</div>
</div>
<div class = "navbar-brand">
<div class="col-sm-2">
<div class="form-group">
<button type="submit" class="btn btn-primary">greetings</button>
</div>
</div>
</div>
<div class = "col-sm-1"></div>
</div>
</div>
</nav>
</body>
</html>
Every example online and similar question online seems to imply that this is all correct.
You want to be looping through your results property returned by your json.
<div class ="container" *ngFor="let item of itemsjson?.results">
<div class="row">
<div class="col-lg-12">
<div class="bs-component">
<div class="jumbotron">
<h1>{{item}}</h1>
</div>
</div>
</div>
</div>
</div>
We also are using the safe navigation operator (?) because itemsjson is not initially defined itemsjson?.results
There is nowhere you are using itemsjson in your HTML, probably you need
<div class="jumbotron">
<h1>{{itemsjson | json }}</h1>
</div>
First, check your itemsjson on console.log and just pass it in your template. If you want to read your data in loop use - *ngFor = 'let data of itemsjson;let i = index' and pass {{data}}.