Displaying Data without *Ngfor - html

I'm trying to display data without using a ngFor loop. It works perfectly but shows all of the quote information from multiple customers. The CSS is laid out in a way that has the discount div next to the customerinfo div Here is the HTML
<hr />
<div class="info">
<div id="CustomerInfoInline" *ngIf="quotes" >
<div *ngFor="let q of quotes">
<h6>Name: {{q.firstName}} {{q.lastName}}</h6>
<h6>Address: {{q.address}}</h6>
<h6>City, State, Zip: {{q.city}}, {{q.state}}, {{q.zip}}</h6>
<h6>SSN: {{q.SSN}}</h6>
<h6>DOB: {{q.dateOfBirth}}</h6>
<h6>Email: {{q.email}}</h6>
<h6>Prev. Carrier: {{q.previousCarrier}}</h6>
<h1>-----------------------------------------------------------------------------------------------</h1>
</div>
</div>
<div *ngIf="quotes">
<div id="CustomerDiscountsInline" *ngFor="let q of quotes">
<h6 id="customerBold">Customer Discounts</h6>
<h4 id="DiscountsID">discounts will be applied here</h4>
</div>
</div>
</div>
<hr />
and the respective TS
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { environment } from '#environments/environment';
import { Quote } from '#app/_models/quote';
import { Router } from '#angular/router';
#Component({
selector: 'app-quote-summary',
templateUrl: './quote-summary.component.html',
styleUrls: ['./quote-summary.component.css']
})
export class QuoteSummaryComponent implements OnInit {
apiUrl: string = environment.apiUrl
quotes: Quote[]
//TODO: implement submitted quote view later
//submittedQuotes: Quote[]
constructor(private http: HttpClient, private router: Router) { }
ngOnInit(): void {
this.getQuotes()
}
// #region API Calls
getQuotes() {
var httpRequest = this.http.get<Quote[]>(`${this.apiUrl}/quotes`)
httpRequest.subscribe(returnedQuotes => {
this.quotes = returnedQuotes
})
}
}

If you need to show only one customer you can use indexer for quotes like quotes[0]:
Don't forgot to check quotes.length > 0:
<div class="info">
<div id="CustomerInfoInline"
<div *ngIf="quotes && quotes.length > 0">
<h6>Name: {{quotes[0].firstName}} {{quotes[0].lastName}}</h6>
<h6>Address: {{quotes[0].address}}</h6>
....
</div>
</div>
</div>

Related

Best way to implement a pageable to Angular Project

I have products in my database and I have created controller on my backend app that I tested and works really good, so now I need to implement that to my frontend. I have product.component.ts file that looks like this
import { Component, OnInit } from "#angular/core";
import { FormControl, FormGroup } from "#angular/forms";
import { debounceTime, switchMap } from "rxjs";
import { ProductService } from "./product.service";
#Component({
selector: 'app-product',
templateUrl: './product.component.html'
})
export class ProductComponent implements OnInit {
products: any[] = [];
productSearchForm!: FormGroup;
page: number = 0;
size: number = 4;
constructor(
private productService: ProductService
) { }
loadMore() {
this.page = this.page+1;
this.productSearchForm.get('searchTerm')?.valueChanges
.pipe(
debounceTime(500),
switchMap(value => {
return this.productService.searchByTermPageable(value, this.page, this.size);
})
).subscribe(data => {
this.products = data;
}, error => {
console.log(error);
// this.products = [];
});
}
ngOnInit(): void {
this.initializeForm();
this.productSearchForm.get('searchTerm')?.valueChanges
.pipe(
debounceTime(500),
switchMap(value => {
return this.productService.searchByTermPageable(value, this.page, this.size);
})
).subscribe(data => {
this.products = data;
}, error => {
console.log(error);
// this.products = [];
});
}
private initializeForm(): void {
this.productSearchForm = new FormGroup({
searchTerm: new FormControl(null)
});
}
}
searchTerm is a query param that is used to find products with name starting with that term. I call function from file product.service.ts that looks like this
import { HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { Observable } from "rxjs";
import { environment } from "src/environments/environment";
#Injectable({ providedIn: 'root'})
export class ProductService {
constructor(private httpClient: HttpClient) { }
searchByTerm(searchTerm: string): Observable<any> {
const url = `${environment.apiUrl}product/search/by-name-or-desc?term=${searchTerm}`;
return this.httpClient.get(url);
}
searchByTermPageable(searchTerm: string, page: number, size: number): Observable<any> {
const url = `${environment.apiUrl}product/search/by-name-or-desc?term=${searchTerm}&page=${page}&size=${size}`;
return this.httpClient.get(url);
}
}
When I click the button load more I want to load next 4 products from database, but keep the first 4 products on my html page, so what is the best way to do this? This is my html page, and also I am using Bulma as my css framework
<div class="mt-5">
<form>
<div class="field" [formGroup]="productSearchForm">
<div class="control has-icons-left">
<input class="input" type="text" formControlName="searchTerm" placeholder="Find products">
<span class="icon is-small is-left">
<i class="fas fa-search"></i>
</span>
</div>
</div>
<hr />
</form>
</div>
<div class="columns">
<div class="column" *ngFor="let product of products">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-content">
<p class="title is-4">{{ product.name }}</p>
<p class="subtitle is-6">{{ product.category?.name}}</p>
</div>
</div>
<div class="content">
{{ product.description }}
</div>
</div>
</div>
</div>
</div>
<button type="button" class="button is-primary" (click)="loadMore()">Load more...</button>
You can to have a new function in your service that return the elements of the page plus the other elements search. If you has a function that return the paginate elements
searchByTermPageable(search:string,page:number,size:number)
{
...
}
Some like
product:any[]=[] //define an empty array where you store the product
searchOld:string=null //and a variable to store the search
getData(search:string,page:number,size:number)
{
if (search!=this.searchOld) //if is a new search
{
this.searchOld=search
this.product=[]
}
return this.searchByTermPageable(search,page,size).pipe(
map((res:any[])=>[...this.product,...res]), //concat the before store product
tap((res:any[])=>{
this.product=res //store in the product the new array
})
)
}
Allow you some like
<div *ngFor="let product of product$|async">
{{product.name}}
</div>
<button (click)="more()">more</button>
pageIndex:number=-1;
product$:Observable<any[]>
more()
{
this.pageIndex++
this.product$=this.dataService.getData("",this.pageIndex,4)
}
The other solution is search all the product and simple use slice pipe
<div *ngFor="let product of allProduct$|async |slice:0:(index+1)*pageSize">
{{product.name}}
</div>
<button (click)="index=index+1">more</button>
a litle stackblitz

Problem with My Wish List Items Showing Source unknown

I am having a problem showing my wish list items on the page. I'm using Angular 10 and json. Wen I click to add to favorites it color the heart and add it to to my json folder under wishlistitem, but when I route to page to look at the items no products are there. I can tell it hits the the *ngFor because the pipe for the dollar amount for each item appears but no images. When inspecting the source it shows src=unknown.
I have two folders wishlist-list and wishlistitem. I have a service for wishlistitem that is where I think my problem resides. I have included my code.
import { Component, OnInit, Input } from '#angular/core';
import {ProductService} from 'src/app/services/product.service'
import { MessengerService } from 'src/app/services/messenger.service';
import { WishlistService } from 'src/app/services/wishlist.service';
import { WishlistItemService } from '#app/services/wishlist-item.service';
import { Wish} from 'src/app/models/wish';
import {Product} from 'src/app/models/product';
#Component({
selector: 'app-wishlist-list',
templateUrl: './wishlist-list.component.html',
styleUrls: ['./wishlist-list.component.scss']
})
export class WishlistListComponent implements OnInit {
productList: Product[]= [];
wishlistItem: Wish[]= [];
wishItem = []
constructor( private msg: MessengerService,
private productService: ProductService,
private wishlistService: WishlistService,
private _wishlistitemService: WishlistItemService ) { }
ngOnInit(): void {
this.loadWishlistList();
}
loadWishlistList(){
this._wishlistitemService.getWishlistitem().subscribe((items: Wish[]) => {
this.wishItem= items;
this.msg.sendMsg("Is the item being captured" + items)
})
}
}
//Here is my Wishlist-list HTML
<p>wishlist-list works!</p>
<div class="container">
<div class="row">
<div class="col-md-2" *ngFor="let product of wishItem">
<app-wishlistitem [wishitemItem]="product"></app-wishlistitem>
</div>
</div>
</div>
//Here is my wishlist item service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { wishlistitemUrl } from 'src/app/config/api';
import { map } from 'rxjs/operators';
import { ProductItemComponent } from '#app/shopping-cart/product-list/product-
item/product-item.component';
import { Observable, of } from 'rxjs';
import { catchError} from 'rxjs/operators';
import {Product} from 'src/app/models/product';
import {Wish} from 'src/app/models/wish';
#Injectable({
providedIn: 'root'
})
export class WishlistItemService {
product:any
wishlistitemUrl = 'http://localhost:3000/wishlistitem';
constructor(private http: HttpClient) { }
getWishlistitem(): Observable<Wish[]>{
return this.http.get<Wish[]>(wishlistitemUrl)
.pipe(
map((result: any[]) => {
let wishItem: Wish[]= [];
for(let item of result) {
let productExists = false
if (!productExists){
wishItem.push(new Wish(item.id, item.name, item.description,
item.price, item.imageUrl);
}
}
return wishItem;
})
);
}
addProductToWishlistItem(product:Wish):Observable<any>{
return this.http.post(wishlistitemUrl, {product});
}
}
//Here is wishlistitem
import { Component, Input, OnInit } from '#angular/core';
import { ProductService } from 'src/app/services/product.service'
import { WishlistService } from 'src/app/services/wishlist.service';
import { WishlistItemService } from '#app/services/wishlist-item.service';
import { MessengerService } from 'src/app/services/messenger.service';
import { map } from 'rxjs/operators';
import { Wish } from '#app/models/wish';
import { Product } from '#app/models/product';
#Component({
selector: 'app-wishlistitem',
templateUrl: './wishlistitem.component.html',
styleUrls: ['./wishlistitem.component.scss']
})
export class WishlistitemComponent implements OnInit {
#Input() wishitemItem: Wish
#Input() productItem: Product
#Input() product: string
constructor(private wishlistService: WishlistService, private _wishlistitemService:
WishlistItemService, private msg:MessengerService ) { }
ngOnInit(): void {
}
//This function works as expected
handleAddToWishlistitem(){
this._wishlistitemService.addProductToWishlistItem (this.wishitemItem).subscribe(()
=>{
alert("Get wish list item");
this.msg.sendMsg(this.wishitemItem)
})
}
}
//Here is wishlistitem Html
<p>wishlistitem works!</p>
<div class="test">
<div class="container" style="margin:0 auto">
<div class="row no-gutters" style="margin-top: 30px">
<div class="col-4">
<img class="shacker" [src]="wishitemItem.imageUrl" />
<div class="card-body">
<p class="card-text" style="text-align:left; width:130px">
{{wishitemItem.name}}</p>
<p class="card-text" style="text-align:left; width:130px;">
<strong>{{ wishitemItem.price | currency }}</strong>
</p>
<p class="card-text" style="text-align:left; width: 150px">
{{wishitemItem.description | slice: 0:20}}...</p>
</div>
</div>
</div>
</div>
</div>
//I hope the explanation is sufficient. I have tried many scenarios, the issue I'm
having is with the property for the wishlist item, carItem does not have a property
and when I create one the application doesn't behave as expected.
Thank you in advance
PDH

Rendering card content on a separate route [Angular]

I am learning MEAN stack. I've deployed my application here. Right now If you click on any card i.e. Read more button, it will automatically take you to a division where contenets are displayed. But I want to show all that content on a separate route or page because now I am planning to provide some more useful options such as Like, Report, Upvote,Donwvote`, etc. So I made some changes. Please look at them.
articles.component.html
<div class="row mt-5">
<div class="col-md-4 mb-3" *ngFor="let article of articles; let i = index;">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">{{article.title}}</h5>
<a (click)="onPress(i)" class="btn btn-primary">Read More</a>
</div>
<div class="card-footer text-muted">
{{article.date}}
</div>
</div>
</div>
</div>
articles.component.ts
import { Component, OnInit } from '#angular/core';
import { ArticlesService } from '../articles.service'; <---- SERVICE FOR READING FROM MONGODB
import {Router, ActivatedRoute }from '#angular/router';
#Component({
...
})
export class ArticlesComponent implements OnInit {
articles=[]
constructor(private _articleService: ArticlesService, private router: Router) { }
ngOnInit() {
this._articleService.getAllArticles()
.subscribe(
res => this.articles = res,
err => console.log(err)
)
}
onPress(id) {
console.log(id); <--- THIS PRINTS INDEX NO OF THE CARD
this.router.navigate(['/options',id]);
}
}
And all the options I mentioned above I've kept them in a separate component.
options-panel.component.html
<div style="margin: 0 auto; width:50vw">
<p> {{data }} </p>
<button (click)="back()"> Back</button>
<div style="display:flex; margin-top:1rem;padding:1rem;">
<button style="margin:0.5rem;"> upVote </button>
<button style="margin:0.5rem;"> DownVote </button>
...
</div>
</div>
options-panel.component.ts
import { Component, OnInit } from '#angular/core';
import {ActivatedRoute,Router } from '#angular/router';
#Component({
...
})
export class OptionsPanelComponent implements OnInit {
private data;
constructor(private router: Router,private activatedRoute: ActivatedRoute) { }
ngOnInit() {
this.activatedRoute.paramMap.subscribe(id =>{
this.data = id.get('id');
})
}
back(){
this.router.navigate(['../'])
}
}
And please review my app-routing.module.ts
...
import { ArticlesComponent } from './articles/articles.component';
import { OptionsPanelComponent } from './options-panel/options-panel.component';
const routes: Routes = [
{path: 'articles', component: ArticlesComponent},
{path:'',redirectTo: 'articles', pathMatch:'full'},
{path: 'options/:id', component:OptionsPanelComponent}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
PS: I read documentation and dependancy injection in Angular. I also tried this stackblitz project.
But I'm getting no errors but blank page.
Please tell me what else I should do now.
What you showed in your picture was working, but you are printing just the id. You must get the article with that id from somewhere, like you service.
There is some information missing about your project, but you could make something like this.
Get the id from the route.
Retrieve your article from your service.
Show it on front using async if possible.
options-panel.component.ts
#Component({
...
})
export class OptionsPanelComponent implements OnInit {
private id: number;
private article$: Observable<Article>;
constructor(private router: Router, private activatedRoute: ActivatedRoute, private _articleService: ArticlesService) { }
ngOnInit() {
this.id = Number(this.activateRoute.snapshot.params['id']);
if (this.id) {
this.article$ = this._articleService.getArticle(this.id);
}
}
back(){
this.router.navigate(['../'])
}
}
options-panel.component.html
<div style="margin: 0 auto; width:50vw" *ngIf="article$ | async as article">
<p> {{ article.content }} </p>
<button (click)="back()"> Back</button>
<div style="display:flex; margin-top:1rem;padding:1rem;">
<button style="margin:0.5rem;"> upVote </button>
<button style="margin:0.5rem;"> DownVote </button>
...
</div>
</div>
If you are seeing that Welcome to my app! and logo, it must be on the index.html file.
If I am not wrong then, you want to create a separate link for each read more. In that case, you have to add router-link in your html and you have to update your routes as well. Try this one:
Your html:
<div class="row mt-5">
<div class="col-md-4 mb-3" *ngFor="let article of articles; let i = index;">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">{{article.title}}</h5>
<a [routerLink]="['/'+article.id]" routerLinkActive="router-link-active" (click)="onPress(i)" class="btn btn-primary">Read More</a>
</div>
<div class="card-footer text-muted">
{{article.date}}
</div>
</div>
</div>
</div>
this html will generate links for each read more. you also have to update your router and have to put your router-outlet in your desired position.
const routes: Routes = [
{
path: 'articles', component: ArticlesComponent,
children: [
{
path: 'id',
component: 'Read more component'
}
]
},
{ path: '', redirectTo: 'articles', pathMatch: 'full' },
{ path: 'options/:id', component: OptionsPanelComponent }
];

Unable to display image from database in angular2?

I am fetching the image URL from the database table and trying to show the image in tag but I am getting an error:-
Hide Copy Code
sanitizing unsafe URL value
if have used
Hide Copy Code
sanitizer.bypassSecurityTrustUrl()
After that the error has been removed but the image is still not been shown.
Here is my code of Component:-
import { Component, OnInit} from '#angular/core';
import { data } from '../Classes/edata';
import { dservice } from '../Service/dataservice';
import {DomSanitizer} from '#angular/platform-browser';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
})
export class HomeComponent implements OnInit {
emp:data[];
constructor(private _eservice:dservice , private sanitizer:DomSanitizer){}
public getSantizeUrl(url:string){
alert(url);
return this.sanitizer.bypassSecurityTrustUrl(url);
}
ngOnInit() {
this.load();
}
load(){
this._eservice.getdata().subscribe((edata)=>this.emp=edata);
}
}
class model:-
export class data
{
id:number;
name:string;
adress:string;
pic:string;
}
Html View:-
<div class="col-md-4 col-sm-6" *ngFor="let e of emp | paginate: {itemsPerPage:5, currentPage:p}">
<div class="property-card card">
<div class="property-card-header image-box">
<img src="{{e.pic}}">
What i tried
<img [src]="getSantizeUrl(e.pic)">

How to put a service in a component and that is displayed in the html? In angular 2

How to put a service in a component and that is displayed in the html by #Input?
Until the moment I carry this code but I have not received success
This is Service
import {
Injectable
} from '#angular/core';
import Rx from 'Rx';
#Injectable()
export class TiempoService {
tiempoTranscurrido: number;
constructor() {}
ngOnInit() {
}
tiempoTotal() {
Rx.Observable.interval(1000).subscribe(segundos => {
this.tiempoTranscurrido = segundos * 1000;
})
}
}
This is component
import {
Component,
OnInit,
Input
} from '#angular/core';
import {
TiempoService
} from "app/servicios/tiempo.service"
#Component({
selector: 'app-menu',
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.css']
})
export class MenuComponent implements OnInit {
#Input() tiemposervice: TiempoService;
constructor() {}
ngOnInit() {
}
}
this is html
<div class="row">
<div class="small-12 columns">
<div class="row">
<div class="small-12 medium-6 columns">
<span>Tiempo transcurrido</span>
<h5>{{tiempoTranscurrido | date:'mm:ss'}}</h5>
</div>
</div>
</div>
</div>
I would greatly appreciate your help
It's best to avoid subscribing ("unwrapping") the observable into a scalar value in the service. Instead, have the service just provide the observable itself, suitably mapped, and consume it in the component. You can consume it directly in the template with the async pipe.
// service
tiempotransCurrido$() {
return Rx.Observable.interval(1000).map(segundos => segundos * 1000);
}
// component
tiempotransCurrido$ = tiempoService.tiempotransCurrido$();
// template
<h5>{{tiempotransCurrido$ | async | date:'mm:ss'}}</h5>
Your component:
export class MenuComponent implements OnInit {
constructor(public tiemposervice: TiempoService) {} //don't forget to add the service to the provider.
}
Your html:
<div class="row">
<div class="small-12 columns">
<div class="row">
<div class="small-12 medium-6 columns">
<span>Tiempo transcurrido</span>
<h5>{{tiemposervice.tiempoTranscurrido| date:'mm:ss'}}</h5>
</div>
</div>
</div>
</div>