In my app, I have a table where the user can enter some stuff to an input field and save them. In the network, the stuff he entered are saved but whenever I refresh the page, the field is empty as if nothing has been entered there. Here is my code, what is wrong with it, and how can I fix it?
HTML:
<ng-container matColumnDef="FilePath">
<th mat-header-cell *matHeaderCellDef> Dosya Yolu </th>
<td mat-cell *matCellDef="let row; let i = index">
<a href (click)="$event.preventDefault()" *ngIf="EditIndex != i">{{row.FilePath}}</a>
<mat-form-field floatLabel="never" *ngIf="EditIndex == i" class="w-100-p">
<input matInput name="FilePath" [(ngModel)]="row.FilePath" type="text">
</mat-form-field>
</td>
</ng-container>
<button mat-icon-button *ngIf="EditIndex != i" (click)="editRow(row, i)">
<mat-icon>edit</mat-icon>
</button>
<button mat-icon-button *ngIf="EditIndex == i"
(click)="editRow(row, undefined)">
<mat-icon>done</mat-icon>
</button>
TS:
testList: ILabConditionResult[] = [];
HPLCFiles: ILabAnalysisFile[] = [];
dataSource: MatTableDataSource<ILabAnalysisFile>;
constructor(){
let data: ILabAnalysisFile[] = [];
this.dataSource = new MatTableDataSource(data);
}
setResponse(response: ILabConditionResult[]) {
if (response) {
response = response.sort((a, b) => {
return a.SequenceNumber - b.SequenceNumber;
});
}
this.testList = response;
if (this.testList && this.testList.length > 0) {
this.HPLCFiles = this.testList[0].HPLCFiles;
this.dataSource.data = this.testList[0].HPLCFiles;
}
}
save(){
this.labConditionResult.HPLCFiles = this.dataSource.data;
this.testList[0].HPLCFiles = this.dataSource.data;
this._labService
.saveAndGetLabTestResultList(this.testList)
.subscribe((response: ILabConditionResult[]) => {
response = response.sort((a, b) => {
return a.SequenceNumber - b.SequenceNumber;
});
this.setResponse(response);
this.setIndex();
response.forEach((x) => {
this.setLabConditionResult(x);
});
}
addNewWorkItem() {
let tempData = this.dataSource.data.splice(0);
tempData.unshift({});
this.dataSource = new MatTableDataSource(tempData);
this.EditIndex = 0;
}
editRow(row: ILabAnalysisFile, index: number) {
if (index == undefined) {
if (
!row.FilePath
) {
return;
}
this.fileList = [];
} else {
this.fileList = [];
}
this.EditIndex = index;
}
The browser can hold data until DOM refreshes, I would recommend save it in localstorage of the browser
// This will store data where Key is identifier and Value can be a dynamic variable
localStorage.setItem(Key, value); // Key & Value should be string before storing
// Retrieve the Value of Key
localStorage.getItem(Key) // String
So according to your code:
// Store Test list from whatever to string
localStorage.setItem("TestList", JSON.stringify(this.testList));
// Retrieve testlist value and change from string to original form
JSON.parse(localStorage.getItem("TestList"));
Related
my cart is only work for data to localstorage but i dont know how can i make this icon switch after click add , than icon change function to remove.
i use awesome font heart for button click :
<a data-id='productID' data-link='productUrl' data-title='productItem' onclick='addItem(this)' title='add to cart'><i class='fa-regular fa-heart fa-xl'></i></a>
<table class='mt-5 table table-bordered' id='collection'></table>
here is script code
class CartItem {
constructor(url, reTitle, reId) {
this.url = url
this.reTitle = reTitle
this.reId = reId
}
}
class LocalCart {
static key = "askCollection"
static getLocalCartItems() {
let cartMap = new Map()
const cart = localStorage.getItem(LocalCart.key)
if (cart === null || cart.length === 0) return cartMap
return new Map(Object.entries(JSON.parse(cart)))
}
static addItemToLocalCart(id, item) {
let cart = LocalCart.getLocalCartItems()
if (cart.has(id)) {
} else
cart.set(id, item)
localStorage.setItem(LocalCart.key, JSON.stringify(Object.fromEntries(cart)))
updateCartUI()
}
static removeItemFromCart(id) {
let cart = LocalCart.getLocalCartItems()
if (cart.has(id)) {
cart.delete(id)
}
if (cart.length === 0)
localStorage.clear()
else
localStorage.setItem(LocalCart.key, JSON.stringify(Object.fromEntries(cart)))
updateCartUI()
}
}
function addItem(e) {
const url = e.dataset.link;
const reTitle = e.dataset.title;
const reId = e.dataset.id;
const item = new CartItem(url, reTitle, reId)
LocalCart.addItemToLocalCart(url, item)
}
function updateCartUI() {
const cartWrapper = document.querySelector('#collection')
cartWrapper.innerHTML = ""
const items = LocalCart.getLocalCartItems()
if (items === 0) return
let count = 0
for (const [key, value] of items.entries()) {
const cartItem = document.createElement('tr')
count += 1;
cartItem.innerHTML =
`
<td width="370" class="record" style="padding:5px">${value.reTitle}</td>
<td width="370" class="record" style="padding:5px">${value.reTitle}</td>
<td width="30" class="record-de"><i class="fa-regular fa-circle-minus"></i></td>
`
cartItem.querySelector('.record-de').addEventListener('click', () => {
LocalCart.removeItemFromCart(key)
})
cartWrapper.append(cartItem)
}
}
document.addEventListener('DOMContentLoaded', () => {
updateCartUI()
})
If fa-heart clicked then save to localstorare (fa-heart change from fa-regular to fa-solid)
if page reload, the fa-heart still in solid icon.
and can the fa-heart change function (toggle switch from add to remove if data has in localstorage)
i try it : https://jsfiddle.net/ceunahteuing/ypq95j3u/15/
Thanks in advance.
How to remove particular data when user click on delete from array stored in local storage ?
the key named title and description in both data are stored in form of array.
this is my script file
let title, description;
function validate() {
title = document.getElementById('title').value;
description = document.getElementById('description').value;
if (title == '') {
alert("Please add title");
} else if (description == '') {
alert("Please add description");
} else {
document.getElementById("myform").reset();
console.log(title);
console.log(description);
store(title, description);
}
}
function store(title, description) {
// load the existing values (default to an empty array if not exist)
let _title = JSON.parse(localStorage.getItem("title") || "[]")
let _description = JSON.parse(localStorage.getItem("description") || "[]")
_title.push(title)
_description.push(description)
localStorage.setItem("title", JSON.stringify(_title))
localStorage.setItem("description", JSON.stringify(_description))
window.location.reload()
}
get_title = JSON.parse(localStorage.getItem("title"))
get_description = JSON.parse(localStorage.getItem("description"))
let table1;
for (i = 0; i < get_title.length; i++) {
if (get_title[i] == null) {
console.log("null")
} else {
table1 += `
<tr>
<th scope="row">${i + 1}</th>
<td id="tit">${get_title[i]}</td>
<td id="descripti">${get_description[i]}</td>
<td>
**
<button type="button"
class="btn btn-sm btn-danger"
onclick="del(${i})">
Delete
</button>
**
</td>
</tr>`
}
}
document.getElementById('table1').innerHTML = table1;
function del(i) {
localStorage.removeItem(`title[${i}]`)
localStorage.removeItem(`description[${i}]`)
window.location.reload()
}
please help me to remove this items.
localStorage and sessionStorage are both key, value storages where both key and value are strings.
You will have to read the arrays
let titles = JSON.parse(localStorage.getItem("title"));
let descs = JSON.parse(localStorage.getItem("descs"));
titles.splice(i, 1);
descs.splice(i, 1);
localStorage.setItem("title", JSON.stringify(titles));
localStorage.setItem("description", JSON.stringify(descs));
I would suggest you store a single array with objects inside like this:
localStorage.setItem('items', JSON.stringify([{ title: 'title1', descirption: 'description1' }]));
Otherwise you risk to have the arrays length out of sync.
Then when you read the array:
let get_items = JSON.parse(localStorage.getItem('items'));
...
get_items[i].title; //reads title
get_items[i].description; //reads description
I'm trying to run the showInfoWindow function only when the map is open at full screen, but so far I can't trace this event.
How can I track the fullsreen event to trigger the function only when the map is open to full screen? How do I move the map-place-selected-wrapper block inside the agm-info-window in this case?
places: Places[] = [];
mapPlaceSelected: any = null;
mapPlaceSelectedShow = false;
loadMoreIndex = 12;
mapCenter: any = [0, 0];
infoWindowOpened: any = null;
showInfoWindow(infoWindow: any, i: number) {
if (this.infoWindowOpened === infoWindow) {
return;
}
if (this.infoWindowOpened !== null) {
this.infoWindowOpened.close();
}
this.infoWindowOpened = infoWindow;
console.log(infoWindow);
}
mapPlaceClick(place: Places, i: number) {
this.mapPlaceSelected = null;
this.mapPlaceSelectedShow = true;
setTimeout(() => {
this.mapPlaceSelected = place;
}, 1);
}
<div class="places-map-wrapper" (clickOutside)="mapPlaceHide()">
<agm-map
[latitude]="mapCenter[0]"
[longitude]="mapCenter[1]"
*ngIf="places.length"
[zoom]="8"
[disableDefaultUI]="false"
[styles]="styles">
<ng-container *ngFor="let place of places; let i = index">
<agm-marker
*ngIf="place.lat && place.long"
(markerClick)="mapPlaceClick(place, i); showInfoWindow(infoWindow, i);"
[latitude]="place.lat"
[longitude]="place.long"
[iconUrl]="'assets/img/map.svg'">
<agm-info-window #infoWindow>
</agm-info-window>
</agm-marker>
</ng-container>
</agm-map>
<div class="map-place-selected-wrapper" [class.active]="mapPlaceSelectedShow">
<span class="b_delete_image" (click)="mapPlaceHide()"></span>
<ng-container *ngIf="mapPlaceSelected">
<ng-container
[ngTemplateOutlet]="placeItem"
[ngTemplateOutletContext]="{place:mapPlaceSelected, index:1}">
</ng-container>
</ng-container>
</div>
</div>
Resolved! I needed to add (fullscreenchange)="fullscreenchange()"
fullscreen: boolean = false;
fullscreenchange() {
if (document.fullscreenElement) {
this.fullscreen = true;
console.log('fullscreen = true!');
} else {
this.fullscreen = false;
console.log('fullscreen = false!');
}
}
<agm-map
[latitude]="mapCenter[0]"
[longitude]="mapCenter[1]"
*ngIf="places.length"
[zoom]="8"
[disableDefaultUI]="false"
(fullscreenchange)="fullscreenchange()"
[styles]="styles">
</agm-map>
fullscreen: boolean = false;
fullscreenchange() {
if (document.fullscreenElement) {
this.fullscreen = true;
console.log('fullscreen = true!');
} else {
this.fullscreen = false;
console.log('fullscreen = false!');
}
}
<div class="places-map-wrapper" (clickOutside)="mapPlaceHide()">
<agm-map
[latitude]="mapCenter[0]"
[longitude]="mapCenter[1]"
*ngIf="places.length"
[zoom]="8"
[disableDefaultUI]="false"
(fullscreenchange)="fullscreenchange()"
[styles]="styles">
<ng-container *ngFor="let place of places; let i = index">
<agm-marker
*ngIf="place.lat && place.long"
(markerClick)="mapPlaceClick(place, i);"
[latitude]="place.lat"
[longitude]="place.long"
[iconUrl]="'assets/img/map.svg'">
<agm-info-window #infoWindow *ngIf="fullscreen">
<div class="map-place-selected-wrapper" [class.active]="mapPlaceSelectedShow">
<ng-container *ngIf="mapPlaceSelected">
<ng-container
[ngTemplateOutlet]="placeItem"
[ngTemplateOutletContext]="{place:mapPlaceSelected, index:1}">
</ng-container>
</ng-container>
</div>
</agm-info-window>
</agm-marker>
</ng-container>
</agm-map>
<div *ngIf="!fullscreen" class="map-place-selected-wrapper" [class.active]="mapPlaceSelectedShow">
<span class="b_delete_image" (click)="mapPlaceHide()"></span>
<ng-container *ngIf="mapPlaceSelected">
<ng-container
[ngTemplateOutlet]="placeItem"
[ngTemplateOutletContext]="{place:mapPlaceSelected, index:1}">
</ng-container>
</ng-container>
</div>
</div>
When the listener "buttAdd.addEventListener" for the add method is triggered: , first this condition works several times(works with the second addition):
if (inputsAdd [0].value ===""||inputsAdd [1].value ===""||inputsAdd [2]
.value === "")
{alert ("fill all fields");}
It works when the fields are not empty, and then the product is added. And if you click on the add button with empty fields, then the product that was added earlier - will be lost. The same story awith the method, delete. Help me please to fix it
//Product Creation Class
class Product {
constructor(name, count, price) {
this.name = name;
this.count = count;
this.price = price;
}
}
Product.SORT_ORDER_ASC = 1;
Product.SORT_ORDER_DESC = -1;
// Сlass where products are recorded
class Shop {
constructor() {
this.products = [];
this.formAdd = document.forms[0];
this.inputsAdd = this.formAdd.elements;
this.buttAdd = this.formAdd.elements[3];
this.formDelete = document.forms[1];
this.nameDelete = this.formDelete.elements[0];
this.buttDelete = this.formDelete.elements[1];
}
//method for adding a product
addProduct(newProduct) {
this.products.push(newProduct);
}
//method for remove product by name
deleteProductByName(productName) {
let i = this.products.length;
while (i--) {
if (productName === this.products[i].name) {
this.products.splice(i, 1);
}
}
}
// get total price by all products
get totalProductsPrice() {
return this.products.map(product => product.price).reduce((p, c) => p + c);
}
//method for sorting the product at its price
sortProductsByPrice(sortOrder) {
const sorted = this.products.sort((a, b) => {
return a.price > b.price ? sortOrder : -sortOrder;
});
this.products = sorted;
}
// method to draw the table with product property (
// name, count, price)
show() {
// add new product by click
this.buttAdd.addEventListener('click', (e) => {
e.preventDefault();
if (this.inputsAdd[0].value === "" || this.inputsAdd[1].value === "" || this.inputsAdd[2].value === "") {
alert("fill all fields");
} else {
this.addProduct(new Product(this.inputsAdd[0].value, parseInt(this.inputsAdd[2].value),
parseInt(this.inputsAdd[1].value)));
this.show();
this.inputsAdd[0].value = "";
this.inputsAdd[1].value = "";
this.inputsAdd[2].value = "";
}
}, false);
// delete product by name after click
this.buttDelete.addEventListener('click', (e) => {
e.preventDefault();
if (this.nameDelete.value === "") {
alert("write a name of product what you want to delete");
} else {
this.deleteProductByName(this.nameDelete.value);
this.show();
this.nameDelete.value = "";
}
}, false);
const rows = document.querySelectorAll("#shop .data");
for (let i = rows.length - 1; i >= 0; i--) {
const e = rows.item(i);
e.parentNode.removeChild(e);
}
const table = document.getElementById("shop");
const tFoot = table.querySelector('tfoot');
if (tFoot) tFoot.remove();
for (let i = 0; i < this.products.length; i++) {
//create table
table.innerHTML += `<tbody><tr class="data"><td>${this.products[i].name}</td>
<td>${this.products[i].price}</td>
<td>${this.products[i].count}</td></tr></tbody>`;
}
//show total price by all products
table.innerHTML += `<tfoot><tr><td colspan="3" id="total-price">Total price:
${this.totalProductsPrice}</td></tr></tfoot>`;
//filter products by price
document.addEventListener("click", (e) => {
let elem = e.target;
if (elem.id === "filter") {
this.sortProductsByPrice(Product.SORT_ORDER_ASC);
this.show();
}
}, false);
console.log(this.products);
}
}
let shop = new Shop();
shop.addProduct(new Product("product", 1, 2000));
shop.addProduct(new Product("product1", 2, 500));
shop.addProduct(new Product("product2", 3, 1000));
shop.show();
<div class="Shop">
<div class="add-product">
<h1>Add product</h1>
<form id="addForm">
<label for="name" >Name of product</label>
<input type="text" id="name" class="input-product">
<label for="price">Price of product</label>
<input type="text" id="price" class="input-product">
<label for="count">Count of product</label>
<input type="text" id="count" class="input-product">
<button id="add" type="button">Add</button><!-- *** -->
</form>
</div>
<div class="product-table">
<h2>Products</h2>
<form id="delete-form">
<label for="name-delete">Delete product by name</label>
<input type="text" id="name-delete" class="input-delete">
<button id="delete" type="button">Delete</button>
</form>
<table id="shop">
<caption>Products that are available in the store</caption>
<tr>
<th>Name:</th>
<th id="filter">Price:</th>
<th>Count:</th>
</tr>
</table>
</div>
</div>
See, you're defining let shop = new Shop() and then use this variable in your Shop class, like shop.show(). I strongly recommend you to use this keyword instead of scoped variable (valid for all other shop usage entries).
Now, about
works several times
I assume, that when you call the show() method it registers more event listeners some time. I mean, you call show - it creates new event listeners + sometimes calls itself (huh, it is pretty risky). I suggest you to move listeners declaration to the constructor - so they will be instantinated once (but that will require keeping DOM nodes). Also it would be nice to split your show fucntion to several smaller functions and get rid of self function emit (it will reduce complexity).
I am developing an application using Angular 2.. In my application I am using barcode scanner to scan in the text field and storing those items in the array.
When I scan the item get added to array, but when I scan another item the old item it replace the old value in array.
Below is the piece of code which I am using. Please help me if you see any fix for the weird issue.
import { Component,ViewChild,Input, Output,OnInit,ChangeDetectorRef } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { HeaderComponent } from '../common/header.component';
//import { SaleCart } from '../model/SaleCart';
//import * as $ from "jquery";
declare var jQuery: any
#Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./posapp.component.css']
})
export class TestComponent implements OnInit{
title = 'Treewalker POS';
public cartItems = [];
public query;
public filteredList = [];
public products = [{"id":"3","name":"Pears Soap Original 75gm","sku":"89675432189","price":"32.00","special_price":"32.00","qty":null,"barcode":"89675432189","tax":"5","discount":"0"},{"id":"1","name":"Rin","sku":"1111111111111","price":"11.00","special_price":"11.00","qty":"10.000","barcode":"1111111111111","tax":"5","discount":"0"},{"id":"2","name":"Test 1","sku":"23456","price":"10.00","special_price":"10.00","qty":"10.000","barcode":"23456","tax":"5","discount":"0"}];
constructor() {
}
ngOnInit() {
}
add(item) {
/* check the items in the json data */
let flag = false;
var foodItem = {};
for (let product of this.products) {
if(product.barcode == item) {
flag = true;
foodItem['ctr'] = 1;
foodItem['item'] = product;
break;
}
}
let localCart = [];
if(sessionStorage.getItem("cart")){
localCart = JSON.parse(sessionStorage.getItem("cart"));
//console.log(JSON.stringify(localCart));
}
//console.log("food "+JSON.stringify(this.cart));
if(flag && localCart.length) {
let exist = 0;
for(let i=0; i < localCart.length; i++) {
if(localCart[i].item.barcode == item) {
localCart[i].ctr = parseInt(localCart[i].ctr) + 1;
//console.log("#### "+this.cart[i].ctr+" --- "+item);
exist = 1;
}
}
if(!exist){
localCart.push(foodItem);
}
sessionStorage.setItem("cart",JSON.stringify(localCart));
//this.barcode = "";
}else if(flag){
localCart.push(foodItem);
sessionStorage.setItem("cart",JSON.stringify(localCart));
}
//this.cart = JSON.parse(sessionStorage.getItem("cart"));
//this.itemsCnt = localCart.length;
//console.log("--- "+this.itemsCnt);
console.log(JSON.parse(sessionStorage.getItem('cart')));
//this.onScanProduct.emit(localCart);
}
filter(e) {
//e.preventDefault();
if (this.query !== ""){
this.filteredList = this.products.filter(function(el){
if(el.barcode.toLowerCase() == this.query.toLowerCase()) {
return el.barcode.toLowerCase() == this.query.toLowerCase();
}else{
return el.barcode.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
}
}.bind(this));
/* scanned item will be added to the cart */
console.log(this.filteredList.length);
if(this.filteredList.length > 0 && e.which == 13){
//console.log(JSON.stringify(this.filteredList));
for (let product of this.filteredList) {
//console.log(filter.barcode+"=="+this.query);
if(product.barcode == this.query) {
this.add(product.barcode);
jQuery('#barcode').val("");jQuery('#barcode').focus();
this.filteredList = [];
}
}
}
}else{
this.filteredList = [];
}
}
}
Below is the html template
<div class="content-wrapper">
<section class="content">
<form>
<div class="row">
<!-- sales item add window -->
<!-- end -->
<div class="col-sm-4">
<div class="box box-primary">
<div class="box-body">
<div class="form-group">
<div class="row">
<div class="col-md-9">
<!--<input type="text" class="form-control" id="barcode" name="barcode" [(ngModel)]="barcode" (ngModelChange)="add($event)"
placeholder="Enter item code or scan the barcode" autocomplete="off" />-->
<input id="barcode" type="text" class="form-control validate filter-input" name="query" [(ngModel)]="query" (keyup)="filter($event)" placeholder="Enter item code or scan the barcode" autocomplete="off" [ngModelOptions]="{standalone: true}">
</div>
<div class="suggestions" *ngIf="filteredList.length > 0">
<ul>
<li *ngFor="let item of filteredList" >
<a (click)="select(item)" href="javascript:;">{{item.barcode}} {{item.name}}</a>
</li>
</ul>
</div>
<div class="col-md-3">
<button type="button" class="btn btn-primary" (click)="createnewproduct(newproduct)">New Product</button>
</div>
</div>
</div>
</div> <!-- end of box body -->
</div>
</div>
</div><!-- end of row -->
</form>
</section>
</div>
Below is the input field which is being used to scan the barcode
<input id="barcode" type="text" class="form-control validate filter-input" [(ngModel)]="query" (keyup)="filter()" placeholder="Enter item code or scan the barcode" autocomplete="off">
I am assuming you are using only the function add. I tried to implement in a javascript like in the following code but I am pretty sure you are referencing that object somewhere else and you are changing it. That's my conclusion but I might be wrong.
var factoryP = (function(){
function P() {
this.cart = [];
this.products = [{'barcode': 1, 'name': 'a'}, {'barcode': 1, 'name': 'b'}]
}
function add(item) {
/* check the items in the json data */
//console.log("cart length "+JSON.stringify(this.cart));
let flag = false;
var foodItem = {};
for (let product of this.products) {
if(product.barcode == item) {
//console.log("check "+item);
flag = true;
foodItem['ctr'] = 1;
foodItem['item'] = product;
break;
}
}
if(flag && this.cart.length) {
let exist = 0;
for(let i=0; i < this.cart.length; i++) {
if(this.cart[i].item.barcode == item) {
//console.log("Same product");
this.cart[i].ctr = parseInt(this.cart[i].ctr) + 1;
exist = 1;
}
}
if(!exist){
console.log(foodItem);
this.cart.push(foodItem);
}
}else if(flag){
console.log("step 4 "+item);
this.cart.push(foodItem);
}
}
P.prototype.add = add;
return new P();
});
instanceP = factoryP();
instanceP.add(1);
instanceP.add(1);
instanceP.add(1);
instanceP.add(2);
console.log(instanceP.cart[0].ctr)
//output 3
instanceP.cart[1].ctr
//output 1
Check your code here. Every time you are initializing the foodItem array with empty array. So whenever code will call add method, it will first empty your foodItem array.
Please check my comment in your code below:
add(item) {
let flag = false;
//Akshay: You need to make your changes here. Initialize your foodItem array out of this scope
var foodItem = {};
for (let product of this.products) {
if(product.barcode == item) {
//console.log("check "+item);
flag = true;
foodItem['ctr'] = 1;
foodItem['item'] = product;
break;
}
}