Sharing data with a service - javascript

I'm trying to display the data for every corresponding name(data from json-server) like firstName, lastName, email etc.
user.component.html - this is where I want to display the corresponding data
<div>
<h2>{{selectedUser.firstName | uppercase}} Details</h2>
<div><span>id: </span>{{selectedUser.id}}</div>
<div>
<label>First name:
<input [(ngModel)]="selectedUser.firstName" placeholder="First Name" />
</label>
</div>
<div>
<label>Last name:
<input [(ngModel)]="selectedUser.lastName" placeholder="Last Name" />
</label>
</div>
<div>
<label>Email:
<input [(ngModel)]="selectedUser.email" placeholder="example.com" />
</label>
</div>
<div>
<label>Start date:
<input [(ngModel)]="selectedUser.startDate" placeholder="Start date" />
</label>
</div>
</div>
user.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { User } from '../user';
import { DataService } from '../data.service';
#Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
users: any
constructor(private dataService: DataService) { }
ngOnInit() {
this.dataService.getUsers()
.subscribe(data => this.users = data);
}
}
home.component.html - this is where I display the name for each user and when I click I want to display the content on the user page
<h2>Users</h2>
<ul class="users">
<a routerLink="/user"><li *ngFor="let user of users['users']"
[class.selected]="user === selectedUser"
(click)="onSelect(user)">
<span class="badge">{{user.id}}</span> {{user.firstName}} {{user.lastName}}
</li> </a>
</ul>
home.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Router } from '#angular/router';
import { User } from '../user';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
public users = [];
constructor(private dataService: DataService) { }
ngOnInit() {
this.dataService.getUsers()
.subscribe(data => this.users = data);
}
}
And here is the data.service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { BehaviorSubject } from 'rxjs';
import { Observable } from 'rxjs';
import { User } from "./user";
#Injectable({
providedIn: 'root'
})
export class DataService {
selectedUser: User;
constructor(private http: HttpClient) {}
getUsers(): Observable<User[]>{
return this.http.get<User[]>("http://localhost:3000/users");
}
onSelect(user: User): void {
console.log(user);
this.selectedUser = user;
}
}
It's work when I display the names on the home page.
I've also made this display of data on a single page(home.component) and it worked, but now I must to display it on another page. I've tried to do this with BehaviourSubject but I got stuck.

You are incorrectly accessing the property in your .html files. Example:
<h2>Users</h2>
<ul class="users">
<a routerLink="/user"><li *ngFor="let user of users['users']"
[class.selected]="user === selectedUser"
(click)="onSelect(user)">
<span class="badge">{{user.id}}</span> {{user.firstName}} {{user.lastName}}
</li> </a>
</ul>
Should be:
<h2>Users</h2>
<ul class="users">
<a routerLink="/user"><li *ngFor="let user of users['users']"
[class.selected]="user === dataService.selectedUser"
(click)="dataService.onSelect(user)">
<span class="badge">{{user.id}}</span> {{user.firstName}} {{user.lastName}}
</li> </a>
</ul>

You can let the DataService cache the users for you in a BehaviorSubject and all components bind to users$ property of the DataService.
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs';
import { HttpClient, HttpResponse, HttpErrorResponse } from '#angular/common/http';
import { User } from "./user";
#Injectable({
providedIn: 'root'
})
export class DataService {
isLoading$ = new BehaviorSubject<boolean>(false);
users$ = new BehaviorSubject<User[]>(undefined);
constructor(private http: HttpClient) { }
loadUsers(): void {
this.isLoading$.next(true);
this.http.get<User[]>("http://localhost:3000/users", { observe: "response" }).subscribe(
(res: HttpResponse<User[]>) => {
this.users$.next(res.body);
},
(res: HttpErrorResponse) => this.onError(res),
() => this.isLoading$.next(false)
);
}
private onError(res: HttpErrorResponse) {
console.log(res.message);
}
}

Related

Console.log prints the cart but can't bind it to the html. ANGULAR

What am I doing wrong?
As you can see the console.log prints the output fine but I can't seem to see it on the webpage.
get-cart.component.ts
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Cart } from 'src/app/models/cartModel';
import { UsersService } from 'src/app/services/users.service';
#Component({
selector: 'app-get-one-cart',
templateUrl: './get-one-cart.component.html',
styleUrls: ['./get-one-cart.component.css']
})
export class GetOneCartComponent implements OnInit {
cart: Cart;
constructor(
private route: ActivatedRoute,
private userService: UsersService
) { }
ngOnInit(): void {
const id = this.route.snapshot.paramMap.get('id');
this.userService.getCartForUser(id)
.subscribe(data => {
this.cart = data;
console.log(this.cart)
});
}
}
get-cart.html
<div class="content-box">
<a routerLink="/users">
<button>Back</button>
</a>
<div *ngIf="cart">
<h2>{{cart._id}}</h2>
<p>{{cart.userId}}</p>
<div *ngFor="let product of cart.products">
<p>{{product.productId}}</p>
<p>{{product.quantity}}</p>
<p>{{product.price}}</p>
</div>
</div>
</div>
console.log and webpage outputs
Got the answer! I just had to set
await Cart.find
to
await Cart.findOne

how to show a Blog detail link in Angular

I want to show the Detail of a Blog in a different link in Angular. I already have a Blog file (blog.component.ts) and an Angular service where I can get all the blogs data from an API backend made with Strapi. There is one button in every single blog, which allows you to view the detail or complete Blog in a different link calling the unique ID, that is named 'pagina.component.ts'.
For that purpose, I think I must call the ID of every single Blog.
Here is my blog.component.html, where I already have the list of my blogs:
<section class="articles">
<article class="blue-article" *ngFor="let data of datas; index as i">
<div class="articles-header">
<time>{{ data.fecha }}</time>
<span class="articles-header-tag-blue">{{ data.relevante }}</span>
<span class="articles-header-category">
{{ data.category.name }}
</span>
</div>
<div class="articles-content">
<h1><a title="">{{ data.title }}</a></h1>
<!--<img *ngIf="!data.image" class="foto" [src]="data.image.name" alt="foto">-->
<div *ngIf="data.image">
<img
src="http://localhost:1337{{ data.image.url }}"
alt="foto"
width="100%"
/>
</div>
<p>
{{ data.content }}
</p>
<h3>{{ data.description }}</h3>
</div>
<div class="articles-footer">
<ul class="articles-footer-info">
<li><i class="pe-7s-comment"></i> 7 Respuestas
</li>
<li><i class="pe-7s-like"></i> 1221</li>
</ul>
<a [routerLink]="['./pagina',i]" class="btn">Leer más</a>
</div>
</article>
</section>
Here is my blog.component.ts file
import { Component, OnInit } from '#angular/core';
import { Meta, Title } from '#angular/platform-browser';
import { StrapiService } from '../../../services/strapi.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.scss']
})
export class BlogComponent implements OnInit {
datas:any=[];
errores:string="";
constructor(
public strapiserv:StrapiService,
private router: Router
) { }
ngOnInit(): void {
this.title.setTitle('Blog');
this.strapiserv.getData().subscribe(res=>{
this.datas= res as string[];
}, error =>{
console.log(error);
if(error.status == 0){
this.errores="Código del error: "+error.status+" \n Ha ocurrido un error del lado del cliente o un error de red.";
}else{
this.errores="Código del error: "+error.status+"\n\n"+error.statusText;
}
})
}
}
Here is my Angular service named 'strapi.service.ts'
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class StrapiService {
REST_API: string ='http://localhost:1337/articles';
//https://strapi-dot-gmal-api-313723.uc.r.appspot.com/
httpHeaders = new HttpHeaders().set('Content-Type', 'application/json');
constructor(private httpClient: HttpClient) { }
getData():Observable<any>{
console.log();
let API=this.REST_API;
return this.httpClient.get(API,{headers:this.httpHeaders}) .pipe(
map((data:any) => {
return data;
}), catchError( error => {
return throwError(error);
})
)
}
/*getItem( idx:number ){
return this.data[idx];
}*/
}
And Here is my pagina.component.ts file where I want to show the complete detailed Blog
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Router } from '#angular/router';
import { StrapiService } from '../../../../services/strapi.service';
#Component({
selector: 'app-pagina',
templateUrl: './pagina.component.html',
styleUrls: ['./pagina.component.scss']
})
export class PaginaComponent implements OnInit {
data:any = {};
constructor( private activatedRoute: ActivatedRoute,
private router: Router,
public strapiserv:StrapiService
){
this.activatedRoute.params.subscribe( params => {
this.data = this.strapiserv.getData( params['id'] );
});
}
ngOnInit(): void {
}
}
My routes are:
const routes: Routes = [
{ path: 'blog', component: BlogComponent },
{ path: 'pagina/:id', component: PaginaComponent },
];
There are a lot of issues with what you have done:
The 'i' is the index of the loop, not the 'id' you want to use. I guess the 'id' is a property of data, so you should point to data.id
You don't have to use relative path when using [routerLink] (with brackets)
so replace this:
[routerLink]="['./pagina',i]"
with this:
[routerLink]="['/pagina', data.id]" // remove the '.'
Finally in your blog.component.ts file, your're receiving array of objects so you don't have to cast it as an array of string, this.datas= res; is enough

Why array only brings one object in Angular project?

I'm working with the League of Legends API, more specific with the champion json they bring.
I have this service made with Angular:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders} from '#angular/common/http';
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
}
#Injectable({
providedIn: 'root'
})
export class ChampionsService {
constructor(private http: HttpClient) { }
getChampions(){
return this.http.get('http://ddragon.leagueoflegends.com/cdn/10.23.1/data/es_ES/champion.json');
}
}
This is my .ts file:
import { Component, OnInit } from '#angular/core';
import {ChampionsService } from '../../services/champions.service';
#Component({
selector: 'app-champions',
templateUrl: './champions.component.html',
styleUrls: ['./champions.component.css']
})
export class ChampionsComponent implements OnInit {
public champions;
public arrayChampions;
constructor(private championsService:ChampionsService) { }
ngOnInit(): void {
this.getAllChampions();
}
getAllChampions(){
this.championsService.getChampions().subscribe(
data => { this.champions = data,
this.arrayChampions = Object.entries(this.champions.data).map(([k,v]) => ({ [k]:v })),
this.ArrayIterator();
},
err => {console.error(err)},
() => console.log("Champions cargados")
);
}
ArrayIterator() {
let IteratableArray = Array();
for (let item of Object.keys(this.arrayChampions[0])) {
var eventItem = Object.values(this.arrayChampions[0]);
IteratableArray.push(eventItem);
}
this.arrayChampions = IteratableArray[0];
}
}
And this is the html:
<p>champions works!</p>
{{arrayChampions | json}}
<!-- Cards -->
<div *ngFor="let arrayChampion of arrayChampions" class="card mb-3">
<div class="card-header">
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<a class="text-decoration-none">{{arrayChampion.id}}</a>
</blockquote>
</div>
<div class="card-footer">
</div>
</div>
As you can see, the var "arrayChampions" only brings the first champion (Atrox) when it should bring all the champions as I understand (I'm new at javascript and Angular).
As per your exmaple I have created and stackblitz here, And it made the whole arrayChampions Iterate over its values.
Please find the working stacblitz here
Sample HTML :
<hello name="{{ name }}"></hello>
<!-- {{this.products |json}} -->
<ul>
<li *ngFor="let champ of products | keyvalue">
<label style="font-size: 20px;font-weight: bold;color: red;">
{{champ.key}}
</label>
<ul *ngFor="let item of champ.value | keyvalue">
<li>
{{item.key}} : {{item.value}}
<ul *ngFor="let sub of item.value | keyvalue">
<li>
{{sub.key}} : {{sub.value}}
</li>
</ul>
</li>
</ul>
</li>
</ul>
Sample component.ts :
import { Component } from "#angular/core";
import { HttpClient } from "#angular/common/http";
import { map, catchError, tap } from "rxjs/operators";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
apiURL: string =
"https://ddragon.leagueoflegends.com/cdn/10.23.1/data/es_ES/champion.json";
name = "Angular";
products = [];
constructor(private httpClient: HttpClient) {}
ngOnInit() {
this.getChamp();
}
getChamp() {
this.httpClient.get(this.apiURL).subscribe((data: any) => {
this.products = data.data;
Object.keys(data.data).map((key: any, obj: any) => obj[key]);
});
}
}

Question detail page not working in angular

I created all-question component it is visible but when i click on particular question view that redirect to that id but not got details on the id page. here i attached some files,
Admin Service file
Model file
Detail question component file
Detail question ts file
All question component file
All question ts file
admin.service.ts - this is admin service file
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs';
import { Admin } from "../model/admin";
#Injectable({
providedIn: 'root'
})
export class AdminService {
private ROOT_URL = "http://localhost:3300/questions";
private httpOptions = {
headers: new HttpHeaders().set("Content-Type", "application/json")
};
constructor(private http: HttpClient) { }
getQuestion(): Observable<Admin[]> {
return this.http.get<Admin[]>(this.ROOT_URL);
}
getQue(id: string){
return this.http.get<Admin>(`${this.ROOT_URL}/${id}`);
}
addQue(admin){
return this.http.post<any>(this.ROOT_URL, admin, this.httpOptions);
}
}
**model=>admin.ts** - this is model file
export interface Admin {
description: String,
// alternatives: String
alternatives: [
{
text: {
type: String,
required: true
},
isCorrect: {
type: Boolean,
required: true,
default: false
}
}
]
}
**que-detail.comp.html** - this is question detail component file
<div class="card">
<div class="card-body">
<h4>Question: {{admin.description}}</h4>
<h4>Options: {{admin.alternatives}}</h4>
</div>
</div>
**que-detail.comp.ts** - this is question details ts file
import { Component, OnInit } from '#angular/core';
import { ActivatedRoute } from '#angular/router';
import { Subscription } from 'rxjs';
import { Admin } from '../model/admin';
import { AdminService } from '../service/admin.service';
#Component({
selector: 'app-question-detail',
templateUrl: './question-detail.component.html',
styleUrls: ['./question-detail.component.css']
})
export class QuestionDetailComponent implements OnInit {
id: string;
admin: Admin;
adminSub$: Subscription;
constructor(private adminService: AdminService, private route: ActivatedRoute ) { }
ngOnInit(): void {
this.id = this.route.snapshot.paramMap.get("id");
this.adminSub$ = this.adminService.getQue(this.id).subscribe(admin => {
this.admin = admin;
});
}
}
**all-que.comp.html** - this is all question component file
<div class="card bg-dark text-white my-4 dashboard-bg">
<div class="card-body text-center">
<ul class="questions" *ngIf="admin$ | async as questions">
<li *ngFor="let question of questions">
<h4 class="card-title my-2">{{question.description}}</h4>
<h5 *ngFor="let x of question.alternatives">{{x.text}}</h5>
<a [routerLink]="question._id">View</a>
</li>
</ul>
</div>
</div>
**all-que.comp.ts** - this is all question ts file
import { Component, OnInit } from '#angular/core';
import { Observable } from 'rxjs';
import { Admin } from '../model/admin';
import { AdminService } from '../service/admin.service';
#Component({
selector: 'app-all-question',
templateUrl: './all-question.component.html',
styleUrls: ['./all-question.component.css']
})
export class AllQuestionComponent implements OnInit {
admin$: Observable<Admin[]>;
constructor(private adminService: AdminService) { }
ngOnInit(): void {
this.admin$ = this.adminService.getQuestion()
}
}
Your Question Details Component should be like,
<div class="card">
<div class="card-body">
<h4>Question: {{admin.description}}</h4>
<h5>Options:</h5>
<ng-container *ngFor="alternative of admin.alternatives">
<h6>{{alternative.text}}</h6>
</ng-container>
</div>
You are just using the undefined questions variable ig.

In my component add new Item is not working in angular

All files are attached as below,
component.html - This is component file
component.ts - This is component ts file
admin-service - This is service file
admin.ts - This is model file
add-que.html - This is component html file.
<div>
<form [formGroup]="adminForm" (ngSubmit)="newQuestion()">
<div class="form-group">
<label for="exampleInputEmail1">Question</label>
<input formControlName="description" type="description" placeholder="Enter question"
class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
<small class="text-danger"
*ngIf="!adminForm.get('description').valid && adminForm.get('description').touched">
Please Enter a Question</small>
</div>
<div class="form-group m-auto">
<div class="col-6">
(a)<input formControlname="alternatives" type="text">
(b)<input formControlname="alternatives" type="text">
</div>
<div class="col-6">
(c)<input formControlname="alternatives" type="text">
(d)<input formControlname="alternatives" type="text">
</div>
</div>
<div class="m-auto">
<input type="submit" value="Add" class="btn btn-primary"/>
</div>
</form>
</div>
**add-que.ts** - This is component ts file.
import { Component, OnInit } from '#angular/core';
import { FormControl, FormGroup, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import { AdminService } from '../service/admin.service';
#Component({
selector: 'app-add-question',
templateUrl: './add-question.component.html',
styleUrls: ['./add-question.component.css']
})
export class AddQuestionComponent implements OnInit {
adminForm = new FormGroup({
description: new FormControl("", [Validators.required]),
alternatives: new FormControl("", [Validators.required])
});
constructor(private adminService: AdminService, private router: Router) { }
ngOnInit(): void {
}
newQuestion(){
if(this.adminForm.valid){
this.adminService.addQue(this.adminForm.value).subscribe(res => {
this.adminForm.reset();
this.router.navigate(["/admin"]);
})
}
}
}
**admin-service.ts** - This is service ts file.
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs';
import { Admin } from "../model/admin";
#Injectable({
providedIn: 'root'
})
export class AdminService {
private ROOT_URL = "http://localhost:3300/questions";
private httpOptions = {
headers: new HttpHeaders().set("Content-Type", "application/json")
};
constructor(private http: HttpClient) { }
getQuestion(): Observable<Admin[]> {
return this.http.get<Admin[]>(this.ROOT_URL);
}
getQue(id: string){
return this.http.get<Admin>(`${this.ROOT_URL}/${id}`);
}
addQue(admin){
return this.http.post<any>(this.ROOT_URL, admin, this.httpOptions);
}
}
**admin.ts** - This is model ts file.
export interface Admin {
description: String,
alternatives: [
{
text: {
type: String,
required: true
},
isCorrect: {
type: Boolean,
required: true,
default: false
}
}
]
}
I did created add-question component with form as above. I did tried to add new question through form in angular but not get anything. i did attached my files as above.
you sould'nt use this.router.navigate(["/admin"]); to try "refresh a component". That's no work (there are no changes). In general you has a component with a ngOnInit. Simply get out the code under a ngOnInit in a function and call this function in subscribe, e.g.
ngOnInit()
{
this.init()
}
init()
{
..here you initialize your variables
}
submit(){
...
.subscribe(res=>{
....
this.init()
})
}

Categories

Resources