Can't get the specific user information to be displayed on the page in Angular - json

I have come across the problem, namely I cannot get the program to display the info of the specific user when clicking on it. The best I could manage is the displaying of every user together. Can you help me with this problem?
Here is the code:
service.ts :
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http'
import {Observable} from 'rxjs';
# Injectable({providedIn: 'root'})
export class JSONPlaceholderpostsService {
constructor(private http: HttpClient) { }
getData():Observable<any> {
const url = "https://jsonplaceholder.typicode.com/users"
return this.http.get<any>(url)}}
The Component.ts:
import { Component, OnInit } from '#angular/core';
import { JSONPlaceholderpostsService } from 'src/app/posts/jsonplaceholderposts.service';
# Component({
selector: 'app-userinfo',
templateUrl: './userinfo.component.html',
styleUrls: ['./userinfo.component.css']})
export class UserinfoComponent implements OnInit {
data:Array<any>
constructor(private JSONPlaceholder: JSONPlaceholderpostsService,){
this.data = new Array<any>()}
ngOnInit(): void {this.getUserInfoFromAPI()}
getUserInfoFromAPI(){
this.JSONPlaceholder.getData().subscribe((data) => {
console.log(data)this.data = data})}
And the component.html file:
<p>USER INFO</p>
<ul *ngFor="let element of data">
<li><button (click)="getUserInfoFromAPI()">{{element.id}}</button></li>
<li><button (click)="getUserInfoFromAPI()">{{element.name}}</button></li>
<li><button (click)="getUserInfoFromAPI()">{{element.email}}</button></li>
<li><button (click)="getUserInfoFromAPI()">{{element.adress}}</button></li>
</ul>
<button ><a hrer="#" routerLink="/userposts" routerLinkActive="actvie">POSTS</a></button>
Thank you all in advance
what I want to happen is that instead of the list of every user just the specific user info to be displayed.

here how I may make it work
for the route I will use the id instead of the name
{path: 'userinfo/:id', component: UserinfoComponent}
and then for useInfo, I will take the user id from the route and filter the list to to get the user and then use this user
Html
<p>USER INFO</p>
<ul >
<li><button (click)="getUserInfoFromAPI()">{{user.id}}</button></li>
<li><button (click)="getUserInfoFromAPI()">{{user.name}}</button></li>
<li><button (click)="getUserInfoFromAPI()">{{user.email}}</button></li>
<li><button (click)="getUserInfoFromAPI()">{{user.adress}}</button></li>
</ul>
<button ><a hrer="#" routerLink="/userposts" routerLinkActive="actvie">POSTS</a></button>
and ts
import { Component, OnInit } from '#angular/core';
import { JSONPlaceholderpostsService } from '../posts/jsonplaceholderposts.service';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-userinfo',
templateUrl: './userinfo.component.html',
styleUrls: ['./userinfo.component.css'],
})
export class UserinfoComponent implements OnInit {
user: any = '';
constructor(private JSONPlaceholder: JSONPlaceholderpostsService, private route: ActivatedRoute) {
}
ngOnInit(): void {
this.getUserInfoFromAPI();
}
getUserInfoFromAPI() {
this.JSONPlaceholder.getData().subscribe((data) => {
const userID = this.route.snapshot.paramMap.get('id') || "";
[this.user] = data.filter((user) => user.id == userID);
});
}
}

Related

Angular service not passing form data after routing

New to Angular and I feel like there's just an obvious mistake I am missing, code-wise.
I'm trying to follow the tutorial here: https://youtu.be/CUAHJxWGia0
I have one component to create/add an employee's ID called CreateEmployee.
On submission, it should route to a component to list all employees (ListEmployees).
It's using employee.service.ts.
When I click submit (before or without routing), it correctly logs the employee input to the console on CreateEmployee.
The problem is that when routing to the second component, ListEmployees, my new entry is not displayed at all, and only my test data is displayed.
I've made sure EmployeeService is included in my app.module as well.
create-employee.ts:
import { Component, OnInit } from '#angular/core'
import { FormControl, FormBuilder, NgForm } from '#angular/forms'
import { EmployeeService } from 'app/services/employee.service'
import { Router } from '#angular/router'
import { Employee } from 'app/shared/employee.model'
#Component({
selector: 'app-create-employee',
template: ` <form class="" [formGroup]="employeeForm" (ngSubmit)="saveEmployee()">
<div class="form-control">
<app-input
#memberID
name="memberID"
label="Member ID"
formControlName="memberID"
placeholder="Member ID"
></app-input>
</div>
<div><button type="submit" class="">Save</button></div>
</form>
{{ employeeForm.value | json }}
`,
styleUrls: ['./create-employee.component.scss'],
})
export class CreateEmployeeComponent implements OnInit {
employeeForm: any
constructor(private fb: FormBuilder, private _employeeService: EmployeeService, private _router: Router) {}
employee: Employee = {
memberID: null,
}
ngOnInit(): void {
this.employeeForm = this.fb.group({
memberID: new FormControl(''),
})
this.employee = this.employeeForm.get('memberID').value
}
saveEmployee() {
this._employeeService.save(this.employee)
console.log(this.employeeForm.get('memberID').value)
// this._router.navigate(['employee-list'])
}
}
list-employee.ts
import { Component, OnInit } from '#angular/core'
import { Employee } from 'app/shared/employee.model'
import { EmployeeService } from 'app/services/employee.service'
#Component({
selector: 'app-list-employees',
template: `<div *ngFor="let employee of employees">
<div class="">
{{ employee.memberID }}
</div>
</div> `,
styleUrls: ['./list-employees.component.scss'],
})
export class ListEmployeesComponent implements OnInit {
employees: Employee[] = []
constructor(private _employeeService: EmployeeService) {}
ngOnInit(): void {
this.employees = this._employeeService.getEmployees()
}
}
employee.service.ts
import { Injectable } from '#angular/core'
import { Employee } from 'app/shared/employee.model'
#Injectable({
providedIn: 'root',
})
export class EmployeeService {
listEmployees: Employee[] = [{ memberID: '1' }, { memberID: '2' }]
constructor() {}
getEmployees(): Employee[] {
return this.listEmployees
}
save(employee: Employee) {
this.listEmployees.push(employee)
}
}

Angular and Typescript Sending Post Request

I have a simple page with angular and typescript with just 1 button and 1 text field. I want to make a post request to a link that posts the string written in text box.
my button html:
<a class="button-size">
Add Customer
</a>
and button ts file:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'customer-button123',
templateUrl: './blabla',
styleUrls: ['./clacla']
})
export class AddCustomerButtonComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
text box html:
<mat-form-field>
<input matInput placeholder="Customer Name">
</mat-form-field>
text box ts file:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'customer-text-field',
templateUrl: './blabla2',
styleUrls: ['./clacla2']
})
export class CustomerTextFieldComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
and simple wrapper page html is:
<div class="input-label">
<mg-customer-text-field></mg-customer-text-field>
</div>
<div>
<mg-customer-button123></mg-customer-button123>
</div>
How can i send a post reques to link localhost8080/admin/addCustomer ?
If you hosting your front end at port: 4200 (default Angular port serve) and you want to send a request to http://localhost8080/admin/addCustomer, you will need a proxy configuration. You can see right here for more info: https://itnext.io/angular-cli-proxy-configuration-4311acec9d6f
You use the HttpModule
I use a service to separate http requests.
Example
import { Component, OnInit } from '#angular/core';
import { ApiService } from '../../services/api.service';
#Component({
selector: 'customer-button123',
templateUrl: './blabla',
styleUrls: ['./clacla']
})
export class AddCustomerButtonComponent implements OnInit {
data: any;
results: any;
constructor(private apiService: ApiService) { }
ngOnInit() {
}
getDataFromApi() {
this.apiService.getData(this.data).subscribe(results => {
this.results = results;
});
}
ApiService
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class ApiService {
apiUrl: string = environment.apiUrl;
constructor(private http: HttpClient) {}
getData(data): any {
return this.http.get(`http://localhost:8080/api/get-data`);
}
html
<div class="input-label">
<mg-customer-text-field [(ngModel)]="data"></mg-customer-text-field>
</div>
<div>
<mg-customer-button123 (click)="getDataFromApi()"></mg-customer-button123>
</div>

Adding a Popup Window with Angular TypeScript

Basically, I would like for a Popup window to appear when I click on this button:
<a (click)="open()" class='btn btn-primary m-r-5px'>
<span class='glyphicon glyphicon-eye-open'></span> View
</a>
To do this, I used the following example.
Here's how I applied the example to my app:
This is my popup HTML code:
<div class="modal-header">
<h4 class="modal-title">Challenge Details</h4>
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- HTML table for displaying a challenge details -->
<table class='table table-hover table-responsive table-bordered'>
<tr>
<td class="w-40-pct">Name</td>
<td>{{challenge?.name}}</td>
</tr>
<tr>
<td>Duration</td>
<td>${{challenge?.duration}}</td>
</tr>
<tr>
<td>Description</td>
<td>{{challenge?.description}}</td>
</tr>
<tr>
<td>Quiz</td>
<td>{{challenge?.Quiz.title}}</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
</div>
Here's it's typescript file view-one-challenge.component.ts:
import { Component, OnInit, Input } from '#angular/core';
import {NgbModal, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-view-one-challenge',
templateUrl: './view-one-challenge.component.html',
styleUrls: ['./view-one-challenge.component.css']
})
export class ViewOneChallengeComponent implements OnInit {
#Input() name;
#Input() duration;
#Input() description;
#Input() title;
constructor(public activeModal: NgbActiveModal) { }
ngOnInit() {
}
}
And here's the typescript file of the component where I want the popup to appear chalist.component.ts:
import {Component, OnInit, Output, EventEmitter, NgModule} from '#angular/core';
import {Challenge} from '../../_models/challenge';
import { Quiz } from '../../_models/quiz';
import {User} from '../../_models/user';
import {ChallengeService} from '../../_services/challenge.service';
import {BrowserModule} from '#angular/platform-browser';
import {CommonModule, Location} from '#angular/common';
import {AlertService} from '../../_services';
import { QuizService } from '../../_services/quiz.service';
import { ViewOneChallengeComponent } from '../view-one-challenge/view-one-challenge.component';
import {FormGroup, FormBuilder, Validators} from '#angular/forms';
import {ActivatedRoute, Params, Router} from '#angular/router';
import { NgbModal, NgbModule } from '#ng-bootstrap/ng-bootstrap';
#Component({
selector: 'app-chalist',
templateUrl: './chalist.component.html',
styleUrls: ['./chalist.component.css'],
providers: [ChallengeService, QuizService],
})
#NgModule({
entryComponents: [ViewOneChallengeComponent]
})
export class ChalistComponent implements OnInit {
challenge_list: Array<Challenge>;
challenge: Challenge;
create_challenge_form: FormGroup;
show_create_challenge_html=false;
quizzes: Array<Quiz>;
constructor(
private challengeService: ChallengeService,
private alertService: AlertService,
private route: ActivatedRoute,
private router: Router,
formBuilder: FormBuilder,
private _location: Location,
private modalService: NgbModal) {
}
ngOnInit() {
console.log("inside ngOnInit...");
this.challengeService.getChallenges().subscribe(
data => {
this.challenge_list = data;
this.alertService.success('Récupération des challenges OK', true);
},
error => {
this.alertService.error(error);
});
}
viewChallenge(id: number) {
if (id > 0) {
this.challengeService.getChallengeById(id).subscribe(
data => {
this.challenge = data;
},
error => {
this.alertService.error(error);
});
}
}
// user clicks 'create' button
createChallenge(){
this.show_create_challenge_html = !this.show_create_challenge_html;
}
readOneChallenge(id) {}
updateChallenge(id) {}
deleteChallenge(id) {}
open() {
const modalRef = this.modalService.open(ViewOneChallengeComponent);
modalRef.componentInstance.name = 'World';
}
}
The method that should open the popup once a user clicks on the button is open(), and the button in question is this one:
<a (click)="open()" class='btn btn-primary m-r-5px'>
<span class='glyphicon glyphicon-eye-open'></span> View
</a>
However, when I run the app and clicks on the link that contains the button, i get the following error in my browser's console:
"StaticInjectorError(AppModule)[ChalistComponent -> NgbModal]: \n StaticInjectorError(Platform: core)[ChalistComponent -> NgbModal]: \n NullInjectorError: No provider for NgbModal!"
The example that I'm following clearly states that:
You can pass an
existing component as content of the modal window. In this case
remember to add content component as an entryComponents section of
your NgModule.
So what I did was, I added the ViewChallengeComponent as an entrypoint to my #NgModule in my chalist.component.ts file, still that didn't solve the problem.
Could anyone please tell me what am I doing wrong here?
Your ngbModal should be provided in the providers.
Change your code to this in chalist.component.ts
#Component({
selector: 'app-chalist',
templateUrl: './chalist.component.html',
styleUrls: ['./chalist.component.css'],
providers: [ChallengeService, QuizService, NgbModal],
})
If you want to use this module throughout your application, then it is better that you provide it in app.module.ts
You have to import it and supply it in the providers list. So instead of doing it in chalist.component.ts or any other component individually, you can provide it globally so that all components under app.module can use it.

Parent / Child component communication angular 2

I am failing to implement action button in child_1 component but the event handler is in sub child component child_2 as shown in the following code:
app.component.html (Parent Html)
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
<app-navigation></app-navigation> <!-- Child1-->
</div>
app.component.html (Parent Component)
import { Component } from '#angular/core';
import { ProductService } from './productservice';
import {Product} from './product';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'MobileShirtShoeApp';
}
app.module.ts (Main Module)
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { Product } from './product';
import { ProductService } from './productservice';
import { AppComponent } from './app.component';
import { NavigationComponent } from './navigation/navigation.component';
import { DataTemplateComponent } from './data-template/data-template.component';
#NgModule({
declarations: [AppComponent,NavigationComponent,DataTemplateComponent],
imports: [BrowserModule,HttpModule],
providers: [ProductService],
bootstrap: [AppComponent]
})
export class AppModule { }
navigation.component.html (Child 1 HTML)
<fieldset>
<legend>Navigate</legend>
<div>
<button (click)="loadMobiles()">Mobiles</button> <!--Child_1 Action-->
</div>
<app-data-template></app-data-template>
</fieldset>
navigation.component.ts (Child 1 Component.ts)
import { Component, OnInit } from '#angular/core';
import { ProductService } from '../productservice';
import {Product} from '../product';
import {DataTemplateComponent} from '../data-template/data-template.component';
#Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {
error: string;
productArray: Product[];
constructor(private myService: ProductService){
this.myService = myService;
}
dataTemplateComponent: DataTemplateComponent = new DataTemplateComponent(this.myService);
ngOnInit() {
}
loadMobiles() {
return this.dataTemplateComponent.loadMobiles();
}
}
data-template.component.html (Child 2 HTML) (NOT DISPLAYING DATA)
<fieldset>
<legend>Requested Data</legend>
Welcome
<div>
<ul>
<li *ngFor="let product of productArray">
{{product.id}} {{product.name}} {{product.price}}
<img src="{{product.url}}">
</li>
</ul>
</div>
</fieldset>
data-template.component.ts (Child 2 Component) (Contains Product service calling code)
import { Component} from '#angular/core';
import {Product} from '../product';
import {ProductService} from '../productservice';
#Component({
selector: 'app-data-template',
templateUrl: './data-template.component.html',
styleUrls: ['./data-template.component.css']
})
export class DataTemplateComponent {
error: string;
productArray: Product[];
constructor(private productService: ProductService) {
this.productService = productService;
}
loadMobiles(){
let promise = this.productService.fetchMobiles();
promise.then(productArr => {
return this.productArray = productArr;
}).catch((err) => {
this.error = err;
});
}
}
ProductService.ts
import 'rxjs/add/operator/toPromise';
import {Http, HttpModule} from '#angular/http';
import {Injectable} from '#angular/core';
import {Product} from './product';
#Injectable()
export class ProductService{
http: Http;
constructor(http: Http){
this.http = http;
console.log(http);
}
fetchMobiles(): Promise<Product[]>{
let url = "https://raw.githubusercontent.com/xxxxx/Other/master/JsonData/MobileData.json";
return this.http.get(url).toPromise().then((response) => {
return response.json().mobiles as Product[];
}).catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
Sorry if the code bothers you. So basically i am failing to display service data in child_2.html when an action made in child_1.html.The service working fine and name is ProductService which uses Product.ts as an object to get the data in JSON format. Any kind of help is appreciated.
This doesn't work because the DataTemplateComponent you're instantiating in app-navigation isn't the same instance of DataTemplateComponent as the one on the page. It's a brand new one that you instantiated and that isn't bound to the page at all. What you're trying to achieve is component communication. Specifically, parent / child component communication. There are a number of ways to do this, the cleanest and most flexible / extensible way is with a shared service pattern. Basically, you declare a service with an observable in it that you inject into both services and one updates the observable while the other is subscribed to it, like this:
#Inject()
export class MyComponentCommunicationService {
private commSubject: Subject<any> = new Subject();
comm$: Observable<any> = this.commSubject.asObservable();
notify() {
this.commSubject.next();
}
}
Then provide this service, either at the app module or possibly at the parent component depending on needs then in app navigation:
constructor(private commService: MyComponentCommunicationService) {}
loadMobiles() {
this.commservice.notify();
}
and in data template:
constructor(private commService: MyComponentCommunicationService, private productService: ProductService) {}
ngOnInit() {
this.commSub = this.commService.comm$.subscribe(e => this.loadMobiles());
}
ngOnDestroy() { this.commSub.unsubscribe(); } // always clean subscriptions
This is probably a little unneccessary since you already have the product service there. You could probably just move the load mobiles logic into the product service and have that trigger an observable that the data template service is subscribed to, and have the nav component call the load mobile method on the product service, but this is just meant to illustrate the concept.
I'd probably do it like this:
#Inject()
export class ProductService {
private productSubject: Subject<Product[]> = new Subject<Product[]>();
products$: Observable<Product[]> = this.productSubject.asObservable();
loadMobiles() {
this.fetchMobiles().then(productArr => {
this.productSubject.next(productArr);
}).catch((err) => {
this.productSubject.error(err);
});
}
}
then nav component:
loadMobiles() {
this.myService.loadMobiles();
}
then data template:
ngOnInit() {
this.productSub = this.productService.products$.subscribe(
products => this.productArray = products,
err => this.error = err
);
}
ngOnDestroy() { this.productSub.unsubscribe(); } // always clean subscriptions

Angular 2 select <li> and get the text

I'm doing an angular2 project and I am struggling with this...
I'm trying to get the text of an li of game lobbies when I click on it.
There is an image to give you an idea of what I have:
These are my files:
gamelobby.component.html:
<h2>Game Lobbies</h2>
<div class='games'>
<ul>
<li *ngFor="let m of gameLobby">{{m}}</li>
</ul>
</div>
gamelobby.component.ts:
import { Component, OnInit } from '#angular/core';
import { WebSocketService } from '../services/websocket.service';
#Component({
moduleId: module.id,
selector: 'gamelobby',
styleUrls: [ 'gamelobby.component.css' ],
templateUrl: 'gamelobby.component.html'
})
export class GameLobbyComponent implements OnInit{
gameLobby: string[] = [];
mouseover:boolean = false;
constructor(private websocketService: WebSocketService) {
}
ngOnInit() {
this.websocketService
.getLobbies()
.subscribe((m:any) => this.gameLobby.push(<string>m));
}
}
I have no clue how can I do it, I tried to do (click)="myMethod" to see if it would do something. But I did it wrong...
Is there any way to do it?
Thank you in advance.
What if you try with something like:
<h2>Game Lobbies</h2>
<div class='games'>
<ul>
<li *ngFor="let m of gameLobby" (click)="getValue(m)">{{m}}</li>
</ul>
</div>
import { Component, OnInit } from '#angular/core';
import { WebSocketService } from '../services/websocket.service';
#Component({
moduleId: module.id,
selector: 'gamelobby',
styleUrls: [ 'gamelobby.component.css' ],
templateUrl: 'gamelobby.component.html'
})
export class GameLobbyComponent implements OnInit{
gameLobby: string[] = [];
mouseover:boolean = false;
constructor(private websocketService: WebSocketService) {
}
ngOnInit() {
this.websocketService
.getLobbies()
.subscribe((m:any) => this.gameLobby.push(<string>m));
}
getValue = (item : string) =>{
console.log(item);
}
}
You can just pass the *ngFor iteration variable:
<div class='games'>
<ul>
<li *ngFor="let m of gameLobby" (click)="myMethod(m)">{{m}}</li>
</ul>
</div>
class GameLobbyComponent {
myMethod(m) {
console.log(m);
}
}