How do I reload data after deletion? - html

I have created some posts in my app as html cards. I have a component called PostList, where I am displaying all these cards. On every card I have a delete button to delete that specific card, which works, but after I delete one card, it doesn't disappear from my post list until I manually refresh the page. This is my card:
<div class="card-body">
<h5 class="card-title cut_text">{{post.title}}</h5>
<p class="card-text cut_text" style="text-align: left;">
{{post.text}}
</p>
<span>Read more</span>
<button *appHasRole='["Admin"]' class="ml-5" (click)="deletePost(post.id)" type="button" style="box-shadow: 1px 1px grey;"><em class="fa fa-trash"></em></button>
</div>
And this is the delete function:
#Component({
selector: 'app-post-card',
templateUrl: './post-card.component.html',
styleUrls: ['./post-card.component.css']
})
export class PostCardComponent implements OnInit {
#Input() post: Post;
posts: Post[];
model: any = {};
user: User;
postId: number;
constructor(private postService: PostsService, private toastr: ToastrService,
private route: ActivatedRoute, public accountService: AccountService) {}
ngOnInit(): void {
this.route.params.subscribe((params) => {
console.log(params);
this.postId = params['id'];
});
}
deletePost(id: number) {
this.postService.deletePost(id).subscribe(() =>{
this.toastr.success('Deleted');
}, error => {
console.log(error);
this.toastr.error(error.error);
});
}
}
This is the html of the post list:
<div class=" container mt-3" >
<span *ngFor="let post of posts">
<app-post-card [post]="post" class="item" ></app-post-card>
</span>
</div>
And this is the method to load the posts:
export class PostListComponent implements OnInit {
posts: Post[];
post: Post;
pagination: Pagination;
postParams: PostParams = new PostParams();
constructor(private postService: PostsService) { }
ngOnInit(): void {
this.loadPosts();
}
loadPosts() {
this.postService.getPosts(this.postParams).subscribe(response => {
this.posts = response.result;
this.pagination = response.pagination;
});
}
}
I have tried calling the loadPosts() method after deleting a card, althought it is not very efficient, but it doesn't work, I still have to refresh the page. What can I do so that it automatically disappears after I am deleting it?

You could use #Output from the child component to send the id that was deleted and remove the element corresponding to this id from the posts variable in parent component.
post-card.component.ts
import { Component, Input, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-post-card',
templateUrl: './post-card.component.html',
styleUrls: ['./post-card.component.css']
})
export class PostCardComponent implements OnInit {
#Input() post: Post;
#Output() postRemoved = new EventEmitter(); // <-- custom event
posts: Post[];
model: any = {};
user: User;
postId: number;
constructor(private postService: PostsService, private toastr: ToastrService,
private route: ActivatedRoute, public accountService: AccountService) {}
ngOnInit(): void {
this.route.params.subscribe((params) => {
console.log(params);
this.postId = params['id'];
});
}
deletePost(id: number) {
this.postService.deletePost(id).subscribe(() =>{
this.toastr.success('Deleted');
this.postRemoved.emit(id); // <-- emit the id in the event
}, error => {
console.log(error);
this.toastr.error(error.error);
});
}
}
post-list.component.html
<div class=" container mt-3" >
<span *ngFor="let post of posts">
<app-post-card (postRemoved)="onPostRemoved($event)" [post]="post" class="item" ></app-post-card>
</span>
</div>
post-list.component.ts
onPostRemoved(id: any) {
this.posts = JSON.parse(JSON.stringify( // <-- assign a deep clone
this.posts.filter(post => post.id !== id)
));
}

Related

My codes are not doing get,set,post so what is my codes error how can i fix it?

these are my .ts codes i write these becasue i want to get product details and delete
import { Component, OnInit } from '#angular/core';
import {FormGroup,FormBuilder, FormControl, Validators} from "#angular/forms"
import { ToastrService } from 'ngx-toastr';
import { Product } from 'src/app/models/product';
import { ProductService } from 'src/app/services/product.service';
import { LocalStorageService } from 'src/app/services/local-storage.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-product-delete',
templateUrl: './product-delete.component.html',
styleUrls: ['./product-delete.component.css']
})
export class ProductDeleteComponent implements OnInit {
products: Product[] = [];
dataLoaded = false;
deleteProductForm:FormGroup;
product :Product
productId :number;
constructor(private formBuilder:FormBuilder,
private productService:ProductService
, private toastrService:ToastrService
,private router:Router,
private localStorageService:LocalStorageService) { }
ngOnInit(): void {
this.createdeleteProductForm();
}
createdeleteProductForm(){
this.deleteProductForm = this.formBuilder.group({
productId:["", Validators.required],
})
}
getbyid() {
Number(localStorage)
Number(this.productService)
this.productService.getbyid(Number(localStorage.getItem("productId"))).subscribe(
(response) => {
this.products = response.data;
this.dataLoaded = true;
this.deleteProductForm.setValue({
productId: this.product,
categoryId: this.product.categoryId,
productName: this.product.productName,
unitPrice: this.product.unitPrice
});
},
(responseError) => {
this.toastrService.error(responseError.error);
}
)
}
deleteProduct() {
if (this.deleteProductForm.valid) {
let productModel = Object.assign({}, this.deleteProductForm.value);
productModel.productId=parseInt(productModel.productId);
this.productService.delete(productModel).subscribe(
(response) => {
this.toastrService.success('Lütfen tekrar giriş yapınız');
this.router.navigate(['/login']);
},
(responseError) => {
this.toastrService.error(responseError.error);
}
);
} else {
this.toastrService.error('Bir hata oluştu.');
}
}
}
these are my html codes i trying to do when user sign in a productId after that click the button delete the product in that ıd
<div class="card">
<div class="card-header"><h5 class="title">Ürün Sil</h5></div>
<div class="card-body">
<form [formGroup]="deleteProductForm">
<div class="mb-3">
<label for="productId">ÜrünId'si</label>
<div class="form-group">
<input type="number"
id="productId"
formControlName="productId" class="form-control"
placeholder="productId"/>
</div>
<div class="card-footer" style="background-color: rgb(4, 62, 255)">
<button
class="btn btn-lg btn-outline-success float-end"
(click)="deleteProduct()"
>
Sils
</button>
</div>
and these are my service
delete(product:Product):Observable<ResponseModel>{
let newPath = this.apiUrl + 'products/delete';
return this.httpClient.post<ResponseModel>(newPath, product );
}
getbyid(productId:number) : Observable<ListResponseModel<Product>> {
let newPath = this.apiUrl + 'products/getbyid?productId=' + productId;
return this.httpClient.get<ListResponseModel<Product>>(newPath);
}
what i'm going for is that when the user goes on a productId click the button, I want to delete the data including the Id first, but what's the null time on main at the moment?
note:Value cannot be null. says back-end
in html POST https://localhost:44314/api/products/delete
[HTTP/2 500 Internal Server Error 9591ms gives this error
First of all, have you checked the value of product in the call of delete ?
Also, maybe it's the httpClient.delete you need since it's the best way to delete an object to the back end. I suggest this:
https://angular.io/guide/http#making-a-delete-request

why the cart is always empty ?? is it because im not using data from api?

cart component
there is to divs one when the cart is empty and one when not
when I run it its always empty!
I erased the content inside the divs
when cart Empty show the div below
<div *ngIf="this.items.length == 0">
</div>
when cart contains items show the div below
<div *ngIf="this.items.length != 0" class="container padding-bottom-3x mb-1">
</div>
cart.component.ts
here are all functions in cart component:
#Component({
selector: 'app-cart',
templateUrl: './cart.component.html',
styleUrls: ['./cart.component.css']
})
export class CartComponent implements OnInit {
items:item[]=[];
total:number=0;
public grandTotal!:number;
clearCart(){
this.cartService.clearCart();
this.items = this.cartService.getItems();
}
remove(item:item){
this.cartService.removeItem(item);
this.items = this.cartService.getItems();
}
constructor(private cartService: CartService) {
}
ngOnInit(): void {
this.cartService.getProducts().subscribe(res=>{
this.items=res;
this.total=this.grandTotal=this.cartService.getTotalPrice();
})
}
}
cart.service.ts
here are all functions in cart service:
export class CartService {
cartItems:item[]=[];
public productList=new BehaviorSubject<any>([]);
addToCart(item: item) {
this.cartItems.push(item);
this.productList.next(this.cartItems);
this.getTotalPrice();
}
getTotalPrice():number{
let grandTotal=0;
this.cartItems.map((a:item)=>{
grandTotal+= a.price;
})
return grandTotal;
}
getItems() {
return this.cartItems;
}
clearCart() {
this.cartItems = [];
this.productList.next(this.cartItems);
return this.cartItems;
}
getLength(){
console.log(this.cartItems.length);
return this.cartItems.length;
}
removeItem(item:item){
this.cartItems.splice(this.cartItems.indexOf(item),1);
}
constructor(private http: HttpClient) { }
}
why not working?????
Because you call productList in the wrong way, when you declare public you can access it directly without signature like this.
ngOnInit(): void {
this.cartService.productList.subscribe(res => {
this.items = res;
this.total = this.grandTotal = this.cartService.getTotalPrice();
});
this.cartService.addToCart({item: 'item a'});
this.cartService.addToCart({item: 'item b'});
this.cartService.addToCart({item: 'item c'});
this.cartService.addToCart({item: 'item d'});
}
Result should be show.
<div *ngIf="this.items.length === 4" class="container padding-bottom-3x mb-1">
Hello I'm here
</div>

Angular 13 Parent-Child not Communicating

Trying to get an array from a parent component to a child component. The Angular docs make it look really simple but I'm not sure what I'm doing wrong. The variable is activePost. Angular version is 13
Parent ts file (HomepageComponent):
import { Component, OnInit } from '#angular/core';
import { PostService } from 'src/app/services/post.service';
import { map } from 'rxjs/operators';
import { Post } from 'src/app/models/post.model';
import { ActivatedRouteSnapshot, Router } from '#angular/router';
import { PostDisplayComponent } from '../components/post-display/post-display.component';
#Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.scss']
})
export class HomepageComponent implements OnInit {
posts?: Post[];
category?:'';
currentpost?: Post;
currentIndex = -1;
title = '';
content='';
activePost: Post;
images: string[] =["../assets/img/damwon.jpg",
"../assets/img/FPX.jpg",
"../assets/img/2015skt.webp",
"../assets/img/2017SSG.webp",
"../assets/img/2014SSW.webp",
"../assets/img/TPA.webp",
"../assets/img/Fnatic.webp"]
backgroundImage: string = '';
constructor(private PostService: PostService,
private route: Router) { }
ngOnInit() {
let ran = Math.floor(Math.random()*6);
console.log(ran, Math.random()*100)
this.backgroundImage = this.images[ran];
this.retrieveposts();
}
refreshList(): void {
this.currentpost = undefined;
this.currentIndex = -1;
this.retrieveposts();
}
retrieveposts(): void {
this.PostService.getAll().snapshotChanges().pipe(
map(changes =>
changes.map(c =>
({ id: c.payload.doc.id, ...c.payload.doc.data() })
)
)
).subscribe(data => {
this.posts = data;
});
}
setActivepost(post: Post, index: number): void {
this.currentpost = post;
this.currentIndex = index;
console.log("Post:", post, "Index:", index);
this.activePost = this.currentpost
this.route.navigate(['/Read/'])
}
}
Child ts file (post-display component)
import { Component, OnInit, Input, OnChanges, Output, EventEmitter } from '#angular/core';
import { Post } from 'src/app/models/post.model';
import { PostService } from 'src/app/services/post.service';
import { HomepageComponent } from 'src/app/homepage/homepage.component';
#Component({
selector: 'app-post-display',
templateUrl: './post-display.component.html',
styleUrls: ['./post-display.component.scss']
})
export class PostDisplayComponent implements OnInit {
#Input() activePost: Post;
#Output() refreshList: EventEmitter<any> = new EventEmitter();
currentPost: Post = {
title: '',
description: '',
category:'',
published: false,
content: ''
};
message = '';
constructor(private PostService: PostService) { }
ngOnInit(): void {
console.log(this.activePost)
}
}
Child HTML:
<div class="container" style="padding-top: 200px;">
<div class="post">
ACTIVE POST HERE:
{{activePost}}
</div>
Looking at the console, the child component always returns undefined for activePost. I'm not sure if this is because I dont have anything in the parent html code for the child to look at? I feel like I should just be able to do this in the .ts file.
Help would be appreciated. Let me know if there are other project docs I should share as well.
Edit, added parent html:
<header class="header" [ngStyle]="{'background-image': 'url(' + backgroundImage + ')'}">
<div class="content">
<h1 class="heading">
<span class="small">Samsite:</span>
Stat
<span class="no-fill">check</span>
</h1>
<!--write a blog-->
</div>
</header>
<section class="blogs-section">
<div class="blog-card"
*ngFor="let post of posts; let i = index"
>
<h1>Title: {{ post.title }}</h1>
<h2> Category: {{ post.category }}</h2>
<p class="blog-overview"> Preview: {{ post.description }}</p>
<div class="btn" (click)="setActivepost(post, i)">Read!</div>
</div>
</section>

#viewChild and #ViewChildern gives undefined

I'm working on Angular 9 and want to access an input field after clicking on a button. right now it gives me undefined. I have tried #ViewChild and #viewChildern because I'm using ngIf.
Template.html file
<div class="search-input" #searchDiv *ngIf="serachActive">
<input
#searched
autofocus
type="text"
class="serach-term"
placeholder="Search"
[(ngModel)]="searchTerms"
(ngModelChange)="applySearch()"
/>
<button (click)="toggleSearch(!serachActive)">
<span class="material-icons"> search </span>
</button>
<ul class="search-list">
<li *ngFor="let result of results">
<a [routerLink]="['/', 'video', 'details', result._id]">{{
result.title ? result.title : ''
}}</a>
</li>
</ul>
</div>
Template.ts file
import { Component, OnInit,AfterViewInit,ElementRef,ViewChild,ViewChildren } from '#angular/core';
import { UserService } from '../../../user.service';
import { VideoService } from '../../../services/video.service';
import { Subject } from 'rxjs';
import { distinctUntilChanged, debounceTime } from 'rxjs/operators';
import { Router } from '#angular/router';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css'],
})
export class HeaderComponent implements OnInit,AfterViewInit{
serachActive: boolean = false;
#ViewChildren('searched') searchElement: ElementRef;
#ViewChildren("searched") input: ElementRef;
user;
subject = new Subject<string>();
results = [];
searchTerms;
loggedIn: Boolean = false;
constructor(
private userService: UserService,
private videoService: VideoService,
private router: Router
) {
this.user = this.userService.getUser();
this.loggedIn = this.userService.isAuthenticated();
}
ngOnInit() {
console.log('on init', this.input); //undefined
this.subject
.pipe(debounceTime(400), distinctUntilChanged())
.subscribe((value) => {
this.router.navigate(['search'], { queryParams: { term: value } });
});
}
ngAfterViewInit() {
console.log('on after', this.input); //undefined
}
toggleSearch(toggledata) {
this.serachActive = toggledata;
this.results = [];
this.searchTerms = '';
console.log(this.input) //undefined
console.log(this.searchElement.nativeElement) //undefined
}
applySearch() {
const searchText = this.searchTerms;
this.subject.next(searchText);
this.searchElement.nativeElement.focus(); //undefined
}
menuButtonClick(button){
if(button === "history"){
this.router.navigate(['history'])
}
}
}
Use ViewChild since you're only searching for 1 element ID.
If adding { static: true } or { static: false } in your ViewChild options doesn't work as what is stipulated on Angular Static Query Migration Documentation
Use ChangeDetectorRef instead:
#Component({...})
export class AppComponent {
#ViewChild('searchInput') input: ElementRef;
isShow: boolean = false;
constructor(private cdr: ChangeDetectorRef) {}
toggle(): void {
this.isShow = !this.isShow;
this.cdr.detectChanges(); // Detects changes which this.isShow is responsible on showing / hiding
// the element you're referencing to in ViewChild
if (this.isShow) // If element is shown, console the referenced element
console.log(this.input);
}
}
Have created a Stackblitz Demo for your reference

How to print data for one MySqL record in Angular

I have a table flight in my MySqL database:
I want to show in my Spring Boot application data only for the first record with flight_id=1
Here is my json
myflights-list.component.html:
<h3>Ticket</h3>
<div *ngIf="flight">
<div>
<label>departureCity: </label> {{flight.departureCity}}
</div>
<div>
<label>destinationCity: </label> {{flight.destinationCity}}
</div>
<div>
<label>price: </label> {{flight.price}}
</div>
<div>
<label>flightDuration: </label> {{flight.flightDuration}}
</div>
<div>
<label>transferNumber: </label> {{flight.transferNumber}}
</div>
<div>
<label>departureDate: </label> {{flight.departureDate}}
</div>
<div>
<label>departureTime: </label> {{flight.departureTime}}
</div>
<hr/>
</div>
myflights-list.component.ts
#Component({
selector: 'myflights-list',
templateUrl: './myflights-list.component.html',
styleUrls: ['./myflights-list.component.css']
})
export class MyflightsListComponent implements OnInit {
flight: Flight = new Flight();
flights: Observable<Flight>;
flight_id: number;
constructor(private flightService: FlightService,
private router: Router, private route: ActivatedRoute, private token: TokenStorageService) { }
ngOnInit() {
ngOnInit() {
/* this.flight_id = 1;*/
this.route.params.subscribe(params => { this.flight_id = params['flight_id']; });
this.flightService.getFlight(this.flight_id).subscribe(t => this.flight = t);
this.flight_id = this.flight.flight_id;
this.reloadData();
}
this.reloadData();
}
reloadData() {
this.flights = this.flightService.getFlight(this.flight_id);
}}
flight.ts
export class Flight {
flight_id: number;
departureCity: string;
destinationCity: string;
price: number;
flightDuration: number;
transferNumber: number;
departureDate: Date;
departureTime: Time;
tickets: Ticket[];
}
export class Ticket {
ticket_id: number;
place: number;
user_id: number;
flight_id: number;
}
flight.service.ts
import {Injectable} from '#angular/core';
import {HttpClient} from '#angular/common/http';
import {Observable} from 'rxjs';
import {Flight} from './flight';
#Injectable({
providedIn: 'root'
})
export class FlightService {
private baseUrl = 'http://localhost:8080/api/flights';
constructor(private http: HttpClient) {
}
getFlight(flight_id: number): Observable<Flight> {
return this.http.get<Flight>(`${this.baseUrl}/${flight_id}`);
}
In my Spring Boot it looks like on the picture. Unfortunately, no data for my flight with flight_id=1
Two ways:
Whether You have to subscribe to your service directly to get your data :
this.flightService.getFlight(this.flight_id).subscribe((response) => {
this.flight = response;
});
}
Or, as you'd intended to do using your flights Observable, subscribe also :
reloadData() {
this.flights = this.flightService.getFlight(this.flight_id);
this.flights.subscribe((response) => {
this.flight = response;
});
}}
}}
Need to susbscribe to the getFlight method.
reloadData() {
this.flightService.getFlight(this.flight_id).subscribe((data) => {
this.flights = data
});
}}