how to update setstate array of object values in react js - reactjs

How can I update setChoices object values, Below is an example of my problem:
I m having choices array of object with values. on setstate(setChoices) want to update the object values.
let [choices, setChoices] = useState({
Choices: [
{
OneChoiceWithValueSelected: {
OptionSelected: '15518',
Price: 0.9,
Quantity: 1,
},
ProductOptionId: 5712,
},
],
Note: 'test message',
ProductId: 6,
Quantity: 1,
StoreId: '6',
TableId: 0,
});
const demo = () => {
setChoices({
Choices: [
{
OneChoiceWithValueSelected: {
OptionSelected: '15518',
Price: 100,
Quantity: 12,
},
ProductOptionId: 5712,
},
],
Note: 'its a new message',
ProductId: 6,
Quantity: 10,
StoreId: '10',
TableId: 0,
});
alert(JSON.stringify(choices));
};
return (
<div>
<button onClick={demo}>test</button>
</div>
);

According to you're state structure, you have to update the setChoices part as follows
const demo = () => {
setChoices({
Choices[0].OneChoiceWithValueSelected.OptionSelected: '15518',
Choices[0].OneChoiceWithValueSelected.Price: 100,
Choices[0].OneChoiceWithValueSelected.Quantity: 12,
Choices[0].ProductOptionId: 5712,
Note: 'its a new message',
ProductId: 6,
Quantity: 10,
StoreId: '10',
TableId: 0
})
alert(JSON.stringify(choices))
}
you have to access the 0th array element to update it's attributes, because the OneChoiceWithValueSelected object is the first element of the Choices array and then use object notation to access others.

Related

Remap structure parent object base on child array data and length object

I am trying remap structure data parent base on child array data and length. It's possible to do? Structure array it's good or i need change array object from backend?
There is no id in child arrays.
This is what i have done
this.arrays = [
{
id: '1',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: [
{
bid: 10000,
date: '2022/12/12',
value: 5000,
},
{
bid: 10000,
date: '2022/12/14',
value: 8100,
},
{
bid: 15000,
date: '2022/12/15',
value: 8100,
},
],
},
{
id: '2',
idbid: '0000000001618',
name: 'bio',
rate: '100',
bid: [
{
bid: 8000,
date: '2022/12/13',
value: 8000,
},
],
},
];
// merge all item bid in child array
let allVal: any = [];
allVal = allVal.concat(this.arrays.map((data) => data.bid).flat());
console.log(allVal);
// get unique bid
var uniqueData = [];
allVal.forEach((item) => {
let count = uniqueData.filter((x) => x.value == item.value).length;
if (count == 0) {
uniqueData.push(item);
}
});
console.log(uniqueData);
// find and merge into parent array
const newArrays = uniqueData.map((obj) => {
return this.arrays.find((data) =>
data.bid.some((val) => val.value == obj.value)
);
});
console.log(newArrays);
// remap structure custom arrays of parent
const remapArrays = newArrays.map((obj, index) => {
return {
id: index + 1,
idbid: obj.idbid,
name: obj.name,
rate: obj.rate,
bid: obj.bid[index]?.bid,
date: obj.bid[index]?.date,
value: obj.bid[index]?.value,
};
});
console.log(remapArrays);
but the result is like this
[
{
id: '1',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: 10000,
date: '2022/12/12',
value: 5000,
},
{
id: '2',
idbid: '0000000001618',
name: 'bio',
rate: '100',
bid: 10000,
date: '2022/12/13',
value: 8100,
},
{
id: '3',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: undefined,
date: undefined,
value: undefined,
},
];
and here is what expected output
// output final that exptected
this.customArrays = [
{
id: '1',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: 10000,
date: '2022/12/12',
value: 5000,
},
{
id: '2',
idbid: '0000000001618',
name: 'bio',
rate: '100',
bid: 8000,
date: '2022/12/13',
value: 8000,
},
{
id: '3',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: 15000,
date: '2022/12/15',
value: 8100,
},
];
Here is link for test Stackblitz
There are some things that should be defined more clearly in the question:
Do we expect the value of "idbid" to be the same across all elements of the original array?
Should the resulting array have the first date of each unique bid?
In my answer, I'll be assuming that the answer is "yes" to both.
In the beginning, when merging all child arrays:
allVal.concat(this.arrays.map((data) => data.bid).flat());
We're losing the values that are unique to each parent element: for example, the value of "rate" is "400" for the first parent element and "100" for the second. So before flattening, we need to map each of the bid arrays, so each child element includes the data from the parent element:
// merge all item bids in child arrays
const allVal = this.arrays
.map((dataWithBids) => {
const { id, idbid, name, rate, bid: bidArr } = dataWithBids;
// add data from the parent element to each bid
return bidArr.map((bidData) => ({
idbid,
name,
rate,
...bidData,
}));
})
.flat();
In the following step, getting only unique values can be done the same way as you did, or using the array some method:
// get unique bids
const uniqueData = [];
allVal.forEach((item) => {
const exists = uniqueData.some((x) => x.value == item.value);
if (!exists) {
uniqueData.push(item);
}
});
At this point we have the correct values, and we need to order them by date and add ids:
const sorted = uniqueData
// sort by date
.sort(
(bidData1, bidData2) =>
Date.parse(bidData1.date) - Date.parse(bidData2.date)
)
// add ids
.map((bidData, index) => ({
...bidData,
id: index + 1 // or (index + 1).toString(),
}));
The result of the above sorted array matches the expected output.

Map Angular Array to Object

I have been looking and have found a few good references for transforming arrays to objects, but I can't seem to find my use case. I have an array with the following format
[
{id: 1, name: 'hello', display: false},
{id: 5, name: 'hello2', display: true},
{id: 7, name: 'hello8', display: true},
]
and I would like to map it into something like this
{
5: {id: 5, name: 'hello2'},
7: {id: 7, name: 'hello8'}
}
I have been trying to use the map function, but I can't figure it out since I want the keys of my map to be an id. This is what I have so far but it is obviously wrong.
const myArray = [
{id: 1, name: 'hello', display: false},
{id: 5, name: 'hello2', display: true},
{id: 7, name: 'hello8', display: true},
];
const myMap = myArray.filter(row => row.display)
.map(row => {
return {row.id: {id: row.id, name: row.name}
});
Filter the array, map it to pairs of [id, obj], and convert to an object using Object.fromEntries(). You can use destructuring and rest syntax (...) to remove display.
Notes: if Object.fromEntries() is not supported, change target in TS Config to ES2019.
const arr = [{id: 1, name: 'hello', display: false},{id: 5, name: 'hello2', display: true}, {id: 7, name: 'hello8', display: true}]
const result = Object.fromEntries(
arr.filter(o => o.display)
.map(({ display, ...o }) => [o.id, o])
)
console.log(result)
Another option is to use Array.reduce() to create the object. In that case, you can skip objects with false display.
const arr = [{id: 1, name: 'hello', display: false},{id: 5, name: 'hello2', display: true}, {id: 7, name: 'hello8', display: true}]
const result = arr.reduce((acc, { display, ...o }) => {
if(display) acc[o.id] = [o.id, o]
return acc
}, {})
console.log(result)

Create new array using 2 arrays with Map function in Angular

Is there an efficient way of creating a new array from 2 arrays?
var employees1 = [
{ id: 11, name: 'joe' },
{ id: 12, name: 'mike' },
{ id: 13, name: 'mary' },
{ id: 14, name: 'anne' }
];
var employees2 = [
{ id: 11, message: 'test1' },
{ id: 12, message: 'test2' },
{ id: 13, message: 'test3' },
{ id: 14, message: 'test4' }
];
Iterate employees1 array and get 'message' for matching id from employees2. Resulting in new array:
var employees3 = [
{ id: 11, name: 'joe', message: 'test1' },
{ id: 12, name: 'mike', message: 'test2' },
{ id: 13, name: 'mary', message: 'test3' },
{ id: 14, name: 'anne', message: 'test4' }
];
Is this possible using Map function? Or using a standard foreach suggested?
Iterate over the first array, search for the element in the second array and finally push them to the new array as illustrated below:
var employees3 = [];
employees1.forEach(emp1 => {
const findEmp = employees2.find(emp2 => emp2.id === emp1.id);
if (findEmp) {
employees3.push({
...emp1,
...findEmp
});
}
});
console.log(employees3);
You can use Array#map and Array#find to get the desired output. I am attaching a sample code:
var employees3 = employees1.map(emp => ({
...emp,
...(employees2.find(item => item.id === emp.id) ?? {})
}))

Filter an Array based on multiple values

I have the following simple JSON array:
const personList = [
{
id: 1,
name: "Phil"
},
{
id: 2,
name: "Bren"
},
{
id: 3,
name: "Francis Underwood"
},
{
id: 4,
name: "Claire Underwood"
},
{
id: 5,
name: "Ricky Underwood"
},
{
id: 6,
name: "Leo Boykewich"
}
];
And I would like to filter this by passing an array of ids so something like [1,4] would be passed in and it would only return "Phill" and "Claire Underwood"
This is what the function looks like but I know it's wrong attendeeIds is an array that's passed in [1, 4]:
getAttendeesForEvent: (attendeeIds) => {
if (attendeeIds === undefined) return Promise.reject("No attendee id provided");
return Promise.resolve(personList.filter(x => x.id == [attendeeIds]).shift());
}
I haven't used JS in years. I've looked for examples but they all seem too complex for what I'm trying to achieve. So how can I filter this based on an array of id's passed in?
return Promise.resolve(personList.filter(x => attendeeIds.indexOf(x.id) !== -1));
You want to check if the id of each item your looping over exists inside of attendeeIds. Use Array.indexOf inside of the filter to do that.
This will return an array of { id: #, name: String } objects.
If you want to return just the names of those objects, you can do a map afterwards which will transform an array into another array using the function that you provide.
const filteredNames = personList
.filter(x => attendeeIds.indexOf(x.id) !== -1)
.map(x => x.name);
// ['Phil', 'Claire Underwood']
You could do something in these lines. Hope this helps.
const personList = [{
id: 1,
name: "Phil"
}, {
id: 2,
name: "Bren"
}, {
id: 3,
name: "Francis Underwood"
}, {
id: 4,
name: "Claire Underwood"
}, {
id: 5,
name: "Ricky Underwood"
}, {
id: 6,
name: "Leo Boykewich"
}];
let attendeeIds = [1, 5];
let getAttendeesForEvent = () => {
return new Promise(function(resolve, reject) {
if (attendeeIds === undefined) {
reject("No attendee id provided");
} else {
resolve(personList.filter((x) => attendeeIds.includes(x.id)).map((obj) => obj.name));
}
});
}
getAttendeesForEvent().then((data) => console.log(data))

react-absolute-grid, displayObject issue

I am trying to use this component: https://github.com/jrowny/react-absolute-grid.
The documentation says I should pass a displayObject which renders items.
So I created a displayObject, like the one in the docs which has this render method:
render: function() {
// Supposing your item shape is something like {name: 'foo'}
const { item, index, itemsLength } = this.props;
return <div>Item {index} of {itemsLength}: {item.name}</div>;
}
I passed it to the component like this:
<AbsoluteGrid
items={SampleData.screens}
displayObject={<DisplayObject/>}
onMove={onMoveDebounced}
dragEnabled={true}
responsive={true}
verticalMargin={42}
itemWidth={250}
itemHeight={250}
filteredProp={'name'}
/>
Where SampleData.screens is:
module.exports = {
screens: [
{'url': 'http://invisionapp.com/subsystems/do_ui_kit/assets/img/screens/original-1x/screen-1-1-login.jpg', 'name': 'login', 'sort': 1, 'key': 1},
{'url': 'http://invisionapp.com/subsystems/do_ui_kit/assets/img/screens/original-1x/screen-1-2-sign-up.jpg', 'name': 'signup', 'sort': 2, 'key': 2},
{'url': 'http://invisionapp.com/subsystems/do_ui_kit/assets/img/screens/original-1x/screen-1-3-walkthrough.jpg', 'name': 'walkthrough', 'sort': 3, 'key': 3}
]
};
When I open the page in the browser, I don't see the text from the displayObject.
How can I use the displayObject?
DisplayObject works good when is a function that return the render html, I try creating a different React.Component for it but got some issues
const items = [
{ key: "0", sort: 0, name: 'Test 1', filtered: false },
{ key: "1", sort: 1 ,name: 'Test 2', filtered: false },
{ key: "2",sort: 2, name: 'Test 3', filtered: false},
{ key: "3", sort: 3,name: 'Test 4', filtered: false }
]
function GridItem(props) {
const { item, index, itemsLength } = props;
return <div >
<span>{item.name}</span>
</div>;
}
const AbsoluteGrid = createAbsoluteGrid(GridItem);

Resources