Angular Count Becomes 0 When Page is Refreshed - javascript

In my code, I have a page where the user can scan some labels and gets add to a list. Every time the user scan a label, total and package count above the list gets updated. But when I refresh the page, the counts become 0 as if there is no label on the list. Here is my code. What should I do?
HTML:
<div fxLayout="row" fxLayoutAlign="start center">
<span class="pr-4">{{'Paket : ' + packageCount }}</span>
<span>{{'Adet : ' + totalCount }}</span>
</div>
TS:
constructor(){
this.calculateRemainingValue();
}
addPackage(response: IKoli, barcodeNumber: string): boolean {
this.calculateRemainingValue();
this.isSaved = false;
this.fg1.reset();
return true;
}
calculateRemainingValue() {
if (this.dataSource.data) {
this.packageCount = this.dataSource.data.length;
let totalWeight = 0;
this.dataSource.data.forEach((x) => (totalWeight += Number(x.PaketAdedi)));
this.totalCount = totalWeight;
}
}

How I know this is normal behaviour of angular.
You must save the counter in some place, for example database or you could save it as cookie or save it in localStorage/sessionStorage.
Hope I helped you!

Related

Can anyone tell me why the DOM stops updating the order total in my restaurant app when I remove the LAST item in the array?

I'm working on a restaurant ordering app, and when I add items, it adds and removes them from the total display, but when I remove the FINAL item in the cart, the order total still shows the value of the last item that was removed. Here is a link to my code as well as the function itself that contain the order total:
https://codepen.io/vanessalearnsjavascript/pen/qBKGvQP?editors=0011
function handleOrderSection(){
let totalPriceArray = [];
let invoiceHtml = ``;
let totalPrice = 0;
orderList.forEach(function(chosenItem, index){
invoiceHtml += `
<div class="item-invoice">
<div class="remove-wpr">
<h3 class="item-invoice name">${chosenItem.name}</h3>
<button class="remove-btn" data-remove="${index}">Remove</button>
</div>
<h3 class="item-invoice-price">$${chosenItem.price}</h3>
</div>
`
//console.log(chosenItem)
totalPriceArray.push(chosenItem.price)
//console.log(totalPriceArray)
if(totalPriceArray.length >= 1){
let orderValue = totalPriceArray.reduce(function(total, num){
return total + num
})
console.log(orderValue)
let customOrder = ``
customOrder += `
<div id="order-total" class="total-display">
Order Total:$ ${totalPriceArray.reduce(function(total, num){
return total + num
})}
</div> `
document.getElementById("chosen-items").style.display = "block"
document.getElementById("chosen-items").innerHTML = customOrder
}
})
document.getElementById('ordered-items').innerHTML = invoiceHtml
if(orderList.length >= 1){
modal.style.display = "inline"
completeBtn.style.display = "inline"
} else {
modal.style.display = "none"
completeBtn.style.display = "none"
}
}
Any help is appreciated. Thanks in advance.
I've tried different things like adding the return statement to different parts of the function and even changing the event listeners, and it just continues to confuse me. I don't have too much to add to this part, just that it's been a real head scratcher for me.

Display 'sum' on another page

I am currently having a problem displaying a calculated sum on the next page in javascript/html.
My calculation for defining the sum looks like this, where the 'sum + €' is displayed at the end.
function udregnPant() {
let sum = 0;
for (i = 0; i <= pantListParsed.length; i++) {
let totalPantKr = pantListParsed[i].aPantMoney + pantListParsed[i].bPantMoney + pantListParsed[i].cPantMoney;
sum += totalPantKr;
console.log(sum);
document.getElementById('sumAfPantB').innerHTML = sum + " €.";
}
}
In the following HTML input I want to display the sum as the value instead of '10 €'
<input type="text" name="amount" id="text1" value="10 €." readonly/>
Appreciate your help!
Make use of web storage.
sessionStorage - stores data for one session
sessionStorage.getItem('label')
sessionStorage.setItem('label', 'value')
localStorage - stores data with no expiration date
localStorage.getItem('label')
localStorage.setItem('label', 'value')
Example
function setSum(value) {
localStorage.setItem("sum", value);
}
function getSum() {
return localStorage.getItem("sum");
}
Live Example at JS Bin
References
Share data between html pages
HTML5 Web Storage
After calculating your value, redirect the user to a URL with the value in the query string (See Redirections in HTTP) -- this may look something like
window.location = http://mysite/page2.html?amount=12
On the new page, retrieve the value from the query string using the searchParams property (see URL.searchParams). Could look something like:
let params = (new URL(document.location)).searchParams;
document.getByElementId('text1').value = params.get('amount');
Here is a little example using local Storage, since so doesnt allow local storage try it in jsfiddle and
the code sample as well:
document.getElementById('btnSend').onclick = ()=>{
let total = document.getElementById('txtTotal').value;
if(!isNaN(total) && total > 0){
localStorage.setItem('total', total);
document.getElementById('txtTotal').value = '';
}
}
document.getElementById('btnLastTotal').onclick = ()=>{
var lastTotal = localStorage.getItem('total');
if(lastTotal !=undefined){
alert('last total is:'+lastTotal);
}else{
alert('No records found');
}
}
<input type="text" id="txtTotal">
<br>
<input type="button" id="btnSend" value="Save the total"> <input type="button" id="btnLastTotal" value="get Last Total">
Hope it helps

Passing data between components and use the ngDocheck

We are trying to pass data from one component to another and below is the approach we are taking. When there is no data we want to show the error message and if there is data we show that in the select box.
showGlobalError = true;
constructor(
private psService: ProjectShipmentService,
private pdComp: ProjectDetailsComponent
) {
this.psService.tDate.subscribe(x => this.cachedResults = x);
}
ngOnInit() { }
ngDoCheck() {
if (this.cachedResults.length > 0 && this.count <= 1) {
this.showGlobalError = false;
this.populateArrays();
this.count++;
}
}
populateArrays() {
this.reportingProject = [this.pdComp.rProjectNumber];
this.projectSalesOrder = this.pdComp.rSalesOrder;
this.clearFilter();
// ........
Our HTML looks like below:
<div *ngIf="showGlobalError">
<h6>The reporting project doesn't have any Shippable Items</h6>
</div>
<div id="search-block" class="box-shadow-block">
<span>Reporting Project</span>
<dx-select-box
[items]="reportingProject"
[text]="reportingProject"
[readOnly]="true"
>
</dx-select-box>
</div>
The issue is The Reporting Project number appears in the select box but when I click on the select box and click anywhere else in the page the project number disappears. I am not sure if this has something to do with the ngDoCheck(). Any help is greatly appreciated
set first your showGlobalError to false and do the logic in your ngOnInit.
showGlobalError = false;
in your view:
<div *ngIf="showGlobalError">
<h6>The reporting project doesn't have any Shippable Items</h6>
</div>
<div *ngIf="!showGlobalError" id="search-block" class="box-shadow-block">
<span>Reporting Project</span>
<dx-select-box
[items]="reportingProject"
[text]="reportingProject"
[readOnly]="true"
>
</dx-select-box>
</div>
use following code to get data from service.
this.psService.tDate.subscribe(x => {this.cachedResults = x},
(err) => {},
() => {this.checkForCachedResults()}
);
and write function to execute your conditional check instead of doCheck() like follows
checkForCachedResults() {
if (this.cachedResults.length > 0 && this.count <= 1) {
this.showGlobalError = false;
this.populateArrays();
this.count++;
}
}

Adding more and more <timepicker> issue. if one gets changed it changes all of them

I have a little problem, I repeat timepicker with *ngFor, but it's not working properly if I changed the time in one of them, it changes in all. And all have a different id. AN IDEA TO MAKE THE WORk PROPERLY?`
COMPONENT.HTML :
<div id="schedule" *ngFor="let i of Arr(num).fill(1)"
style="display: -webkit-inline-flex">
<timepicker id="timer" class="schedulItem" style="margin-top:-28px"
[(ngModel)]="mytime" [showMeridian]="isMeridian"
[minuteStep]="mstep" (ngModelChange)="changed()">
</timepicker>
<button (click)="addSchedule()"> + </button>
</div>
COMPONENT.TS:
Arr = Array; //Array type captured in a variable
num:number = 1;
mytime: Date;
addSchedule() {
this.num = this.num + 1 ;
var length = document.querySelectorAll('.schedul').length
var time = document.getElementById("timer");
time.id += length;
}
changed(): void {
var time = this.mytime.getHours() + ":" + this.mytime.getMinutes();
console.log(time);
}
I found the problem! the model was the problem [(ngModel)]="mytime". All time pickers to the same model and one gets changed it changes all of them.

The data binding between html element property and script value not synchronized

Problem description:
There is an availability calendar which displays whether a person is busy on a particular slot (each day is divided to two slots). This state is stored in the isSlotFree boolean 2d array (this array is of size 31 x 2). Initially, all values in this array are initialized to true. Then, a http get request is made to a server requesting the busy dates. Once they are received, the function setIsSlotFree() is called to set the appropriate values in the array to false. In the view (HTML file) there is a <td> element for each slot. Each of these elements update their color (using class styles) based on the boolean value stored in the relevant index of the array. The problem is that the html page does not reflect the changes made to the array after calling the setIsSlotFree() function. (ie. the html elements still see all values as true). However, when I print the array in the console right after the get request, it has changed the appropriate values to false. When any event is triggered, then only the view is updated to the correct values. What is the problem here?
Following are the relevant parts of the component.ts file
export class CalendarComponent implements OnInit {
viewDate: Date;
isSlotFree: boolean[][] = [
[true, true]
];
constructor(private http: HttpClient) {
}
ngOnInit() {
this.viewDate = new Date();
var i: number;
var j: number;
for (i = 1; i < 31; i++) {
this.isSlotFree.push([true, true]);
}
let p = new HttpParams().set('month', (this.viewDate.getMonth() + 1).toString());
this.http.get < busyDateResponse[] > ("http://localhost:51967/api/stylists/getBusyDates", {
params: p
}).subscribe(res => {
this.setIsSlotFree(res);
});
this.x = true;
console.log(this.isSlotFree);
this.viewDate = new Date();
}
setIsSlotFree(res: busyDateResponse[]): void {
var busy_date: busyDateResponse;
for (busy_date of res) {
var temp: number = (busy_date.slot == 'm') ? 0 : 1;
this.isSlotFree[busy_date.day - 1][temp] = false;
}
}
}
interface busyDateResponse {
$id: string;
day: number;
month: number;
year: number;
slot: string;
}
Following shows the relevant parts of the component.html file
<ng-template #cellTemplate let-day="day" let-locale="locale">
<div class="cal-cell-top">
<div class="cal-day-number w3-xlarge">{{ day.date | calendarDate:'monthViewDayNumber':locale }}</div>
<br>
</div>
<div *ngIf="day.inMonth && day.isFuture">
<table style="width:100%">
<tr>
<td class="calendar-slot" [ngClass]="{'w3-green': isSlotFree[day.date.getDate()-1][0], 'w3-red': !isSlotFree[day.date.getDate()-1][0]}">{{isSlotFree[day.date.getDate()-1][0]}}Morning</td>
<mat-checkbox (change)="editSelectedSlots($event)" [checked]="isSelectedSlot(day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_m')?true:false" [id]="day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_m'"
*ngIf="isSlotFree[day.date.getDate()-1][0]"></mat-checkbox>
</tr>
<tr>
<td class="calendar-slot" [ngClass]="{'w3-green': isSlotFree[day.date.getDate()-1][1], 'w3-red': !isSlotFree[day.date.getDate()-1][1]}">{{isSlotFree[day.date.getDate()-1][1]}}Evening</td>
<mat-checkbox (change)="editSelectedSlots($event)" [checked]="isSelectedSlot(day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_e')?true:false" [id]="day.date.getDate() + '_' + day.date.getMonth() + '_' + day.date.getFullYear() + '_e'"
*ngIf="isSlotFree[day.date.getDate()-1][1]">
</mat-checkbox>
</tr>
</table>
</div>
</ng-template>
<div>
<mwl-calendar-month-view [viewDate]="viewDate" [events]="events" (eventClicked)="eventClicked($event)" (dayClicked)="dayClicked($event)" [cellTemplate]="cellTemplate" [refresh]="refresh">
</mwl-calendar-month-view>
<div class="w3-center">
<button mat-raised-button>Make booking</button>
</div>
</div>
Please note that <mwl-calendar-month-view> utilizes the ng-template to generate cells in a calendar.
Well I finally found the solution after reading a lot about change detection in angular. The change detection strategy is executed before running the setIsSlotFree() function.Even though the values in the array are modified, the change detection strategy is not executed when the array values are changed by this function. Therefore, change detection needs to be executed manually after writing all the changes to the array. This can be done using ChangeDetectorRef.detectChanges() at the end of the setIsSlotFree() function.
If the constructor for the component is constructor(private http: HttpClient, private ref: ChangeDetectorRef) then, the isSlotFree() function would look like,
setIsSlotFree(res:busyDateResponse[]):void {
var busy_date:busyDateResponse;
for(busy_date of res) {
var temp:number = (busy_date.slot=='m')?0:1;
this.isSlotFree[busy_date.day-1][temp] = false;
}
this.ref.detectChanges();
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Categories

Resources