i get flat list from server and i must create a tree that list .
this is my model :
export interface ClaimManagerList {
id: number;
title: string;
parentId: number;
isChilde: boolean;
childs: Childes[];
}
export interface Childes {
id: number;
title: string;
parentId: number;
isChilde: boolean;
}
and in this code i convert flat list to tree list -> childs add to this property childs :
return this.claimsManagerService.getAll(this.searchParam).pipe(
map(data => {
data['records'].forEach(element => {
let model = {} as ClaimManagerList;
if (element.parentId == null) {
model.id = element.id;
model.isChilde = element.isChilde;
model.parentId = element.parentId;
model.title = element.title;
data['records'].forEach(child => {
if (child.parentId == element.id) {
let childe = {} as Childes;
childe.id = child.id;
childe.isChilde = child.isChilde;
childe.parentId = child.parentId;
childe.title = child.title;
model.childs.push(childe)
}
})
this.claims.push(model)
}
})
return this.claims;
})
but it show me error in this line :
model.childs.push(childe)
Cannot read property 'push'
whats the problem ? how can i solve this problem ?
This happening as model.childs is not set to an empty array at the beginning. We can resolve this like:
if(!model.childs) model.childs = [] as Childes[];
model.childs.push(childe) // This line should work fine now.
I'm going to propose some changes to your code to order to improve this. I hope these changes will be useful for you.
return this.claimsManagerService.getAll(this.searchParam).pipe(
map((data: any) => {
data.records.forEach((element: any) => {
let model: ClaimManagerList = {};
if (element.parentId == null) {
model.id = element.id;
model.isChilde = element.isChilde;
model.parentId = element.parentId;
model.title = element.title;
model.childs = [];
data.records.forEach((child: any) => {
if (child.parentId == element.id) {
let childe = {} as Childes;
childe.id = child.id;
childe.isChilde = child.isChilde;
childe.parentId = child.parentId;
childe.title = child.title;
model.childs.push(childe)
}
})
this.claims.push(model)
}
})
return this.claims;
})
Related
I have a config object. Using this config object, I populate required elements by appending a string to the key of this object.I need help updating values
const MEMBER_INITIAL_VALUE = {
type: '',
dateOfBirth_: '',
seekingCoverage_: true,
relationshipToPrimary: ''
};
const updateInitialValue = (type, relationshipToPrimary) => {
var newMemberObjValue = JSON.parse(JSON.stringify(MEMBER_INITIAL_VALUE));
let updateValue = Object.entries(newMemberObjValue).forEach(([key, value]) => {
[`${key}_${type}`]: value; //I'm stuck here. not sure how to proceed
delete key;
});
return updateValue;
};
updateInitialValue = ('applicant', 'SELF');
updateInitialValue = ('spouse', 'DEPENDANT');
Expected Result:
{
type: 'applicant',
dateOfBirth_applicant: '',
seekingCoverage_applicant: true
relationshipToPrimary: 'SELF'
};
{
type: 'spouse',
dateOfBirth_spouse: '',
seekingCoverage_spouse: true
relationshipToPrimary: 'DEPENDANT'
};
Since you're not updating the original object, you can simplify this greatly:
const MEMBER_INITIAL_VALUE = {
type: '',
dateOfBirth_: '',
seekingCoverage_: true,
relationshipToPrimary: ''
};
const updateInitialValue = (type, relationshipToPrimary) => ({
type,
relationshipToPrimary,
[`dateOfBirth_${type}`]: MEMBER_INITIAL_VALUE.dateOfBirth_,
[`seekingCoverage_${type}`]: MEMBER_INITIAL_VALUE.seekingCoverage_
});
let updatedValue = updateInitialValue('applicant', 'SELF');
updatedValue = updateInitialValue('spouse', 'DEPENDANT');
This should do the trick:
const MEMBER_INITIAL_VALUE = {
type: '',
dateOfBirth_: '',
seekingCoverage_: true,
relationshipToPrimary: ''
};
const updateInitialValue = (type, relationshipToPrimary) => {
let newMemberInitialValue = JSON.parse(JSON.stringify(MEMBER_INITIAL_VALUE));
Object.keys(newMemberInitialValue).forEach((key) => {
if(!['type', 'relationshipToPrimary'].includes(key)) {
newMemberInitialValue[`${key}_${type}`] = newMemberInitialValue[key];
delete newMemberInitialValue[key];
}
});
newMemberInitialValue.type = type;
newMemberInitialValue.relationshipToPrimary = relationshipToPrimary;
console.log(newMemberInitialValue);
};
let applicantValues = updateInitialValue('applicant', 'SELF');
let spouseValues = updateInitialValue('spouse', 'DEPENDANT');
EDIT: Missed returning the value from the function and then assigning to a new variable.
Although an answer was posted, because i also solved it and my solution is a bit different (though the other answer looks way too slimmer) i would post it here.
const MEMBER_INITIAL_VALUE = {
type: "",
dateOfBirth_: "",
seekingCoverage_: true,
relationshipToPrimary: "",
};
const updateInitialValue = (type, relationshipToPrimary) => {
var newMemberObjValue = JSON.parse(JSON.stringify(MEMBER_INITIAL_VALUE));
Object.entries(newMemberObjValue).forEach(([key, value]) => {
if (key === "type") {
newMemberObjValue[key] = type;
} else if (key === "dateOfBirth_") {
Object.defineProperty(
newMemberObjValue,
[`${key}_${type}`],
Object.getOwnPropertyDescriptor(newMemberObjValue, key)
);
delete newMemberObjValue[key];
newMemberObjValue[`${key}_${type}`] = value;
} else if (key === "seekingCoverage_") {
Object.defineProperty(
newMemberObjValue,
[`${key}_${type}`],
Object.getOwnPropertyDescriptor(newMemberObjValue, key)
);
delete newMemberObjValue[key];
newMemberObjValue[`${key}_${type}`] = value;
} else if (key === "relationshipToPrimary") {
newMemberObjValue[key] = relationshipToPrimary;
}
});
return newMemberObjValue;
};
const updatedValue1 = updateInitialValue("applicant", "SELF");
const updatedValue2 = updateInitialValue('spouse', 'DEPENDANT');
Though a few answers have already been posted, I would like to suggest a similar one that does the same thing in a much more clear and concise way:
function Member() {
this.type = '';
this.dateOfBirth = '';
this.seekingCoverage = true;
this.relationshipToPrimary = '';
}
function UpdateInitialValue(type, relationshipToPrimary) {
var newMember = new Member();
newMember.type = type;
newMember.relationshipToPrimary = relationshipToPrimary;
return newMember;
}
console.log(UpdateInitialValue('applicant', 'SELF'));
console.log(UpdateInitialValue('spouse', 'DEPENDANT'));
I have a problem with some class for cart , which I must use in my work.
Here is code of this class:
class Cart {
constructor() {
this.key = "IT_SPA_CART";
if (!this.exists()) {
this.setItSpaCart([]);
}
}
get() {
const cookies = document.cookie.split(";");
return cookies.find(cookie => cookie.startsWith(this.key));
}
exists() {
return this.get() !== undefined;
}
getItSpaCart() {
const cookieValue = this.get().slice(12);
const parsedValue = JSON.parse(cookieValue);
return parsedValue;
}
setItSpaCart(value) {
const stringifiedValue = JSON.stringify(value);
document.cookie = `${this.key}=${stringifiedValue}`;
}
add(item) {
const cartValue = this.getItSpaCart();
this.setItSpaCart([...cartValue, item]);
}
remove(item) {
const cartValue = this.getItSpaCart();
const itemInCart = cartValue.findIndex(val => val.name === item.name);
if (itemInCart !== -1) {
cartValue.splice(itemInCart, 1);
this.setItSpaCart(cartValue);
}
}
}
When I try to use this class, e.g. with method add(), like this:
let cart = new Cart();
cart.add([{ num: 1, cost: 2 }, { num: 3, cost: 4 }, { num: 5, cost: 6 }]);
this error occur:
Cannot read property 'slice' of undefined at Cart.getItSpaCart
Why this is happend?
Thanks for every hint.
I had the same problem ;-) Maybe You already know how to fix it, but if not, perhaps solution is changing code in this line: const cookies = document.cookie.split(";");. I changed ("; ) into ("; ").
I am building up an ecommerce web in which i have my order Model class like this
import { User } from './user.model';
export class Order {
constructor(){}
amount: Number = 0;
status: String = "";
date: String = '';
products: [any];
userId: String = '';
user : User;
}
And user model like this
export class User{
name: string = '';
email: string = '';
country: string = '';
city: string = '';
mobileNumber: string = '';
address: string = '';
postalCode : string = '';
nearBy : string = '';
_id : string = '';
}
And i have a cart.service.ts in which i am calculating an order total amount like this
// Total amount
public getTotalAmount(): Observable<number> {
return this.cartItems.pipe(map((product: CartItem[]) => {
return products.reduce((prev, curr: CartItem) => {
return prev + curr.product.price * curr.quantity;
}, 0);
}));
}
Now on my checkout.component.ts i am binding values to order Model class like this
isUserLoggedIn: boolean = false;
orderRawData: any;
order: Order;
placeOrder() {
this.cartService.getTotalAmount().subscribe(total=>{
if (total) {
console.log('amount : ',total);
this.order.amount = total;
this.orderRawData = JSON.parse(localStorage.getItem('cartItem'));
if (this.isUserLoggedIn) {
this.order.userId = this.user._id;
}else{
this.order.user = this.user;
}
this.orderRawData.forEach((item,index)=>{
this.order.products.push({
id : item.product._id,
quantity : item.quantity
})
})
this.order.date = new Date().toLocaleString();
this.order.status = 'Pending';
console.log(this.order);
}
})
}
But it's giving me an error like this
What am i doing wrong?
You have declared order:
order: Order;
Bu it never gets assigned an object, so is undefined when you try to updated one of its properties.
this.order.amount = total;
// <--- undefined here
You somehow need to assign order, for example:
this.orderService.getOrder().subscribe(order => {
this.order = order;
});
Before you can consider updating properties on it.
Your order follows the 'Order' format but it's not initialize.
You can do like this:
1) order: Order = {
amount: 0,
status: null,
....
}
or 2) Update the Order class like:
export class Order {
amount: Number;
status: String;
...
constructor(_amount: Number = 0, _status: String = '', ...) {
this.amount = _amount;
this.status = _status;
....
}
}
In the component:
order: Order = new Order();
Current config (cannot update it to latest):
"#angular/cli": "^7.3.9",
"primeng": "7.0.5",
I have a PrimeNG p-table that has lazy loaded data with pagination.
There is an issue open for it on PrimeNG GitHub too - https://github.com/primefaces/primeng/issues/8139
Stackblitz link is already attached in that issue so didn't create a new one.
Scenario:
One 1st page, some rows are selected via checkbox selection.
On 2nd page, Select All checkbox from the header is selected and all rows on 2nd page is auto-selected.
Now when navigated to the first page, the selections from here are reset. But the Select All checkbox in the header is still checked.
Would like to know if anyone has a workaround for this issue?
Any help is appreciated.
Edit:
Solution found in another similar GitHub issue: https://github.com/primefaces/primeng/issues/6482
Solution:
https://github.com/primefaces/primeng/issues/6482#issuecomment-456644912
Can someone help with the implementation of the override in an Angular 7/8 application. Not able to understand as how to get the TableHeaderCheckbox reference and override the prototype.
Well, the solution to the problem is still not added to the PrimeNG repo and so even the latest package does not have it solved.
For time being, use the solution mentioned in the question under Edit
To answer the question that I have asked under the Edit, check below:
// In some service file:
import { Table, TableHeaderCheckbox } from 'primeng/table';
import { ObjectUtils } from 'primeng/components/utils/objectutils';
import { uniq, each, intersection, map, remove } from 'lodash';
#Injectable()
export class BulkSelectAllPagesService {
overridePrimeNGTableMethods() {
TableHeaderCheckbox.prototype.updateCheckedState = function () {
const currentRows = map(this.dt.value, this.dt.dataKey);
const selectedRows = map(this.dt.selection, this.dt.dataKey);
this.rowsPerPageValue = this.dt.rows;
const commonRows = intersection(currentRows, selectedRows);
return commonRows.length === currentRows.length;
};
Table.prototype.toggleRowsWithCheckbox = function (event, check) {
let _selection;
if (!check) {
_selection = this.value.slice();
each(_selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(this._selection, match);
});
} else {
_selection = check ? this.filteredValue ? this.filteredValue.slice() : this.value.slice() : [];
each(this._selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(_selection, match);
});
this._selection = this._selection.concat(_selection);
}
this.preventSelectionSetterPropagation = true;
this.updateSelectionKeys();
this.selectionChange.emit(this._selection);
this.tableService.onSelectionChange();
this.onHeaderCheckboxToggle.emit({
originalEvent: event,
affectedRows: _selection,
checked: check
});
};
}
// In app.component.ts
import { Component, OnInit } from '#angular/core';
import { BulkSelectAllPagesService } from 'PATH_TO_THE_FILE/bulk-select-all-pages.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
constructor(
private bulkSelectAllPagesService: BulkSelectAllPagesService) {
}
ngOnInit() {
this.bulkSelectAllPagesService.overridePrimeNGTableMethods();
}
}
Ofcourse need to include the service file in the providers[] in the app.module.ts
Will create a stackblitz and add later.
Improved version to handle rowspan grouped data:
overridePrimeNGTableMethods() {
TableHeaderCheckbox.prototype.updateCheckedState = function () {
const currentRows = map(this.dt.value, this.dt.dataKey);
const uniqueCurrentRows = uniq(currentRows);
const selectedRows = map(this.dt.selection, this.dt.dataKey);
this.rowsPerPageValue = this.dt.rows;
const commonRows = intersection(currentRows, selectedRows);
if (currentRows.length) {
return commonRows.length === uniqueCurrentRows.length;
} else {
return false;
}
};
Table.prototype.toggleRowWithCheckbox = function (event, rowData) {
const findIndexesInSelection = (selection: any = [], data: any = {}, dataKey: any) => {
const indexes = [];
if (selection && selection.length) {
selection.forEach((sel: any, i: number) => {
if (data[dataKey] === sel[dataKey]) {
indexes.push(i);
}
});
}
return indexes;
};
this.selection = this.selection || [];
const selected = this.isSelected(rowData);
const dataKeyValue = this.dataKey ? String(ObjectUtils.resolveFieldData(rowData, this.dataKey)) : null;
this.preventSelectionSetterPropagation = true;
if (selected) {
const selectionIndexes = findIndexesInSelection(this.selection, rowData, this.dataKey);
const selectedItems = this.selection.filter((val: any) => {
return val[this.dataKey] === rowData[this.dataKey];
});
this._selection = this.selection.filter((val: any, i: number) => {
return selectionIndexes.indexOf(i) === -1;
});
this.selectionChange.emit(this.selection);
selectedItems.forEach((selectedItem: any, index: number) => {
this.onRowUnselect.emit({ originalEvent: event.originalEvent, index: event.rowIndex + index, data: selectedItem, type: 'checkbox' });
});
delete this.selectionKeys[rowData[this.dataKey]];
} else {
let rows = [rowData];
if (dataKeyValue) {
rows = this.value.filter(val => {
return (val[this.dataKey]).toString() === dataKeyValue;
});
}
this._selection = this.selection ? this.selection.concat(rows) : rows;
this.selectionChange.emit(this.selection);
this.onRowSelect.emit({ originalEvent: event.originalEvent, index: event.rowIndex, data: rowData, type: 'checkbox' });
if (dataKeyValue) {
this.selectionKeys[dataKeyValue] = 1;
}
}
this.tableService.onSelectionChange();
if (this.isStateful()) {
this.saveState();
}
};
Table.prototype.toggleRowsWithCheckbox = function (event, check) {
let _selection;
if (!check) {
_selection = this.value.slice();
each(_selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(this._selection, match);
});
} else {
_selection = check ? this.filteredValue ? this.filteredValue.slice() : this.value.slice() : [];
each(this._selection, (row) => {
const match = {}; match[this.dataKey] = row[this.dataKey];
remove(_selection, match);
});
this._selection = this._selection.concat(_selection);
}
this.preventSelectionSetterPropagation = true;
this.updateSelectionKeys();
this.selectionChange.emit(this._selection);
this.tableService.onSelectionChange();
this.onHeaderCheckboxToggle.emit({
originalEvent: event,
affectedRows: _selection,
checked: check
});
};
}
With my angular2 application, i am getting the response and assigning to object as follows,
seatingConcession: {
parking: data.concession.extras.parking ? data.concession.extras.parking : null,
restrictedview: data.concession.extras.restrictedview ? data.concession.extras.restrictedview : null,
wheelchair: data.concession.extras.wheelchair ? data.concession.extras.wheelchair : null
}
sometimes extras does not have value. sometimes restrictedview inside extras does not have value. what is the best way to check and assign the default value .
Whole code:
this.eventService.getListingsByEventId(this.eventId).subscribe(listresults => {
this.bindListing(listresults);
}, error => this.errorMessage = error);
}
bindListing(listres: any[]) {
let price_table = {};
let section_table = {};
listres.forEach((data) => {
data.ticket.seating.forEach((seat: any) => {
// tslint:disable-next-line:max-line-length
this.listings.push({
section: seat.section, selling: data.price.selling, amount: data.ticket.amount, type: data.ticket.type, row: seat.row, category: seat.category,
seatingConcession: {
parking: data.concession.extras ? (data.concession.extras.restrictedview || null) : null,
restrictedview: data.concession.extras.restrictedview || null,
wheelchair: data.concession.extras.wheelchair || null
},
deliveryconcession: {
instantdownload: data.delivery.instantdownload || null,
readytoship: data.delivery.readytoship || null,
unespecifiedshipment: data.delivery.unspecifiedshipment || null
}
});
// this.listings.push({ section: seat.section, selling: data.price.selling, amount: data.ticket.amount, type: data.ticket.type, row: seat.row, category: seat.category});
// tslint:disable-next-line:curly
if (!price_table.hasOwnProperty(data.price.selling))
price_table[data.price.selling] = [];
price_table[data.price.selling].push(data);
// tslint:disable-next-line:curly
if (!section_table.hasOwnProperty(seat.section))
section_table[seat.section] = [];
section_table[seat.section].push(data);
});
});
Service js:
getListingsByEventId(EventID: string): Observable<ListingSeller[]> {
let apiurl = this.appConfig.getAPIUrl() + '/getListingsByEventId';
return this.http
.get(apiurl + queryString)
.map(this.extractData)
.catch(this.handleErrors);
}
You can use the following function to achieve what you want.
function getSafe(fn) {
try {
return fn();
} catch (e) {
return null;
}
}
Then use it like this
seatingConcession: {
parking: getSafe(() => data.concession.extras.parking),
restrictedview: getSafe(() => data.concession.extras.restrictedview),
wheelchair: getSafe(() => data.concession.extras.wheelchair),
}
See details.
Another approach would be to execute data.concession.extras = data.concession.extras || {} before actually creating your object.
You mentioned,
"sometimes extras does not have value. sometimes restrictedview inside extras does not have value"
so, this condition will help you.
data.concession.extras ? (data.concession.extras.restrictedview || data.concession.extras ) : null
Here is an example:
The first example has restrictedview and the second example doesn't.
data = {}
data.concession = { 'extras' : {} }
data.concession.extras = { 'restrictedview' : 'restrictedview value'}
data2 = {}
data2.concession = { 'extras' : 'extras value' }
var output = data.concession.extras ? (data.concession.extras.restrictedview || data.concession.extras ) : null
var output2 = data2.concession.extras ? (data2.concession.extras.restrictedview || data2.concession.extras ) : null
console.log(output)
console.log(output2)
PLEASE RUN THE ABOVE SNIPPET
Observables do try...catch, so for data structures it is possible to follow the pattern:
data$
.map(data => data.complex.path || null)
.catch(() => Observable.of(null))
But for nested structures this will result in complex observable hierarchy which is hard to comprehend.
So basically it is possible to treat complex paths to values with this recipe:
parking: ((data.concession || {}).extras || {}).parking || null
This case is conveniently treated by Lodash/Underscore get or a similar helper function:
parking: _.get(data, 'concession.extras.parking', null)