I am trying to add values inside the object id. Object id is created before but I want to add more values in the future inside the object ID.
This is my MongoDB database:
[{
label: 'colors',
options: [
{ label: 'Black', value: 1 },
{ label: 'Green', value: 2 },
]
}]
My expectation is when I will send a new object it will insert a new object inside the options property. suppose my new object is {label: 'blue', value: 3} it will be like this:
[{
label: 'colors',
object: [
{ label: 'Black', value: 1 },
{ label: 'Green', value: 2 },
{label: 'blue', value: 3}
]
},
I am trying this way, I am storing the previous data value, inserting a new value, and sending it to the backend. but it's not working. is there any different way I can fix it?
const addAttributeValues = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (label === '') {
return
}
const slug = label?.split(' ').join('-')
const options: any = [] // previous value storing
let update; // inserting previous and new value
if (attr.options) { // checking if the previous data has options property or not
options.push(attr.options)
const length: any = options.length
update = { options: { ...options, [length]: { label, slug } }, id: attr._id }
}
else { // if option property doesn't exist it means no new value added before
update = { options: { label, slug }, id: attr._id }
}
fetch('http://localhost:5000/dashboard/attributes', {
method: 'PUT',
headers: { 'content-type': 'application/json' },
body: JSON.stringify(update)
})
.then(res => res.json())
.then(data => {
setLabel('')
setIfShouldUpdate(true)
})
}
Backend API, I use put method, I don't know is there any other method for inserting new values in the future.
// ADD ATTRIBUTES VALUE
app.put('/dashboard/attributes/', async (req, res) => {
const { options, id } = req.body
const filter = { _id: objectId(id) }
const updateDoc = {
$set: {
options: options
},
};
const result = await unityMartAttributes.updateOne(filter, updateDoc);
res.json(result)
console.log(result);
})
You need to use $push to add new object in your array. $set will reset your previous values with new one. Also don't use ObjectId, just pass simple id which needs to be string. And if you want to pass in ObjectId then use
mongoose.Types.Objectid(id)
Related
I am using the NHL api to try to grab players stats for a given season. I have a utility function with these season values :
export const seasonOptions = [
{ value: "19861987", label: "1986/1987" },
{ value: "19871988", label: "1987/1988" },
{ value: "19881989", label: "1988/1989" },
{ value: "19891990", label: "1989/1990" },
{ value: "19901991", label: "1990/1991" },
{ value: "19911992", label: "1991/1992" },
{ value: "19921993", label: "1992/1993" },
{ value: "19931994", label: "1993/1994" },
{ value: "19941995", label: "1994/1995" },
{ value: "19951996", label: "1995/1996" },
];
... and so on. In my component I have this state to setSelect on what was selected:
const [select, setSelect] = useState(seasonOptions[seasonOptions.length - 1]);
const handler = (selected) => {
setSelect((select) => select);
handlePlayerStats(
`https://statsapi.web.nhl.com/api/v1/people/${props.playerId}/stats?stats=statsSingleSeason&season=${selected.value}`
);
}
};
<Select
id="select"
instanceId={"select"}
options={seasonOptions}
placeholder={select.label}
autoFocus
value={select.value}
onChange={handler}
/>
Which calls this custom hook:
const handlePlayerStats = async (url) => {
try {
const req = await fetch(url).then((response) => response.json());
console.log(req);
if (req.messageNumber) {
setFetchedData([]);
} else if (req.stats[0].splits.length > 0) {
setFetchedData(req);
}
} catch (error) {
console.log(error);
}
};
I'm not really sure how to go about looping through all the seasonOptions dynamically and filtering out each season where req.stats[0].splits.length === 0?
Here is the codesandbox link for anyone curious: https://codesandbox.io/s/friendly-kapitsa-c97rzy?file=/components/PlayerStats.js:357-855
To Answer The first parst of your question you can map over this Array of Objects with this method for example using the .map method
React Code SandBox
MDN-.map() method JS
export const seasonOptions = [
{ value: 8471214, label: "198601987" },
{ value: 8471215, label: "198701988" },
{ value: 8471216, label: "198801989" },
{ value: 8471217, label: "198901990" },
{ value: 8471218, label: "199001991" },
{ value: 8471219, label: "199101992" },
{ value: 8471220, label: "199201993" },
{ value: 8471221, label: "199301994" },
{ value: 8471222, label: "199401995" },
{ value: 8471223, label: "199501996" },
];
//MAKE SURE TO MAP OVER THE <option></option> tag not the <Select/>
//CHECK CODE SANDBOX FOR EXAMPLE IN PURE HTML5 AND REACT
{seasonOptions.map((option,index)=>
<Select
key={index}
id="select"
instanceId={"select"}
options={option?.value}
placeholder={option?.label}
autoFocus
value={select.value}
onChange={handler}
/>
)}
Check Out my Answer Here or for other examples here how to map over an array and access it values this method is just 1 of many .
How to find a value from array object in JavaScript? Stack Over Flow Question
For the Second Part Of the Question you can use the new SandBox
Steps
Change the value property here from a string to a number by removing the quotation marks export const seasonOptions = [{value: 8471214, label: "198601987"},]
Assign a useState hook to handle the active filtered item
const [activeFilter, setActiveFilter] = useState([]);
3.Assign an arrow function to handle Filtering the Seasons
using the setTimeOut() method setTimeout()-MDN-DOCS Where 500 is the time the function is executed for that time and
const handleSeasonsFilter = (item) => {
setActiveFilter(item);
setTimeout(() => {
if (!item) {
setFilterSeasons(item);
} else {
setFilterSeasons(
seasonOptions.filter((season) =>
seasonOptions?.includes(season?.label)
)
);
}
}, 500);
};
Pass that to url that searches the API url = `https://statsapi.web.nhl.com/api/v1/people/${activeFilter}/stats?stats=statsSingleSeason&season=200402005 Like in Line 65 in The Sand Box
Display Them using useEffect() hook also add in the values in the dependency array or leave it empty to avoid infinite loops.
useEffect(() => {
//debug data
console.log(stringDataDisplay);
setActiveFilter(activeFilter);
//DEBUG IF VALUE IF PASSED
//setDatasearched(activeFilter);
}, [
/**EMPTY DEPENDENCY ARRAY TO AVOID INFINITE LOOPS */
stringDataDisplay,
activeFilter
]);
in My Example i Displayed Them using another useState Hook and State action
const [datasearched, setDatasearched] = useState([])
& Finally Just Assigned a new const stringDataDisplay = JSON.stringify([datasearched]);
To Stringify the [datasearched] Array Here.
Note
Make sure to pass the handleSeasonsFilter to OnClick as an empty arrow function and pass the option.value property as a String so the API Accepts the request.
Hope this helps with your Example and Ill try to Check the code sandbox also with your method.
Bear in Mind i still i am developing this and i understand you want the values of the seasons to be shown when no player id is selected Am i correct?
I am using multiple dropdown list and fetching the data based on url. There are two dropdowns like below.
1 . data: [{"id": 1, "value":"Shoe"},{"id": 2, "value":"Clothing"}] --> categories
url -> '/api/products/category'
2. data : [{ "category_name": "Shoe", sizes: ['7','8','9'] }] --> available sizes
url -> '/products/${item_id}/category/${category_id}
Now, i am using service and vuex action to load dropdown based url.
Here is service
export async function fetchItemsOfDrowdown(url) { // passing the url
const resp = await http.get(url);
return resp.data;
}
Here is the action
async fetchDropdownItems({ state, commit }, payload) {
if (!state.fieldItems[payload.key]) {
const items = await service.fetchItemsOfDrowdown(payload.url);
const parsedItems = [];
for (let i = 0; i < items.length; i += 1) {
const item = items[i];
parsedItems.push({
text: item[payload.text],
value: item[payload.value]
});
}
commit('DropdownFieldItems', {
key: payload.key,
items: parsedItems
});
}
}
Mutation
DropdownFieldItems(state, payload) {
state.fieldItems = {
...state.fieldItems,
[payload.key]: payload.items
};
}
How i am configuring dropdown fields type
fields : {
category_id: {
key: 'category_id',
label: 'Category',
uri: '/products/category',
value: '',
items: []
},
product_size: {
key: 'product_size',
label: 'Available Size',
value: '',
uri: '/products/${item_id}/category/${category_id}
items: []
}
}
Calling the action into action and passing the data like this
created() {
if (this.fields && Object.keys(this.fields).length > 0) {
const fieldKeys = Object.keys(this.fields);
for (let i = 0; i < fieldKeys.length; i += 1) {
const key = fieldKeys[i];
if (this.fields[key] && this.fields[key].uri) {
this.fetchDropdownItems({
key,
url: this.fields[key].uri,
text: 'value',
value: 'id'
});
}
}
}
},
I want to store dropdown fields into state like this.
payload: object --> items: Array[2] key --> "category_id" --> for 1st one working fine
I want to format the 2nd url payload so we can store it as same as 1st one. How to format the 2nd payload structure like 1st one in action itself?
I'm trying to create new object with different properties name from Array.
Array is:
profiles: Array(1)
0:
column:
name: "profileName"
title: "Profile name"
status: "Active"
I want to create new function that return object with two properties:
id: 'profileName',
profileStatus: 'Active'
The function that I have create is returning only one property as undefined undefined=undefined.
function getProfile(profiles) {
if (!profiles.length) return undefined;
return profiles.reduce((obj, profile) => {
console.log('profiles', profile);
return ({
...obj,
id: profile.column.name,
profileStatus: profile.status,
});
}, {});
}
The function getProfile is taking as input array 'profiles' from outside,
I've just tested here and this seems to be working actually
const getProfile1 = (p) => p.reduce((obj, profile) =>({
...obj,
id: profile.column.name,
profileStatus: profile.status,
}), {});
You can use map as an alternative.
var profiles = [{"column":{"name": "profileName3","title": "3Profile name"},"status": "Active"},{"column":{"name": "profileName","title": "Profile name"},"status": "Active"}];
function getProfile(profiles) {
if (!profiles.length) return undefined;
return profiles.map(function(profile,v){
return {id:profile.column.name,profileStatus: profile.status};
});
}
console.log(getProfile(profiles));
Whenever I use reduce in this way, I usually index the final object by some sort of an id. As noted in another answer, you could use map in this situation as well. If you really want your final data structure to be an object, however, you could do something like this:
/**
* returns object indexed by profile id
*/
const formatProfiles = (profiles) => {
return profiles.reduce((obj, profile) => {
return {
...obj,
[profile.id]: {
id: profile.column.name,
profileStatus: profile.status,
}
};
}, {});
};
const profiles = [
{
id: 0,
status: 'active',
column: {
name: "profile_name_1",
title: "profile_title_1",
},
},
{
id: 1,
status: 'inactive',
column: {
name: "profile_name_2",
title: "profile_title_2",
}
}
];
const result = formatProfiles(profiles);
/**
* Result would look like this:
*/
// {
// '0': { id: 'profile_name_1', profileStatus: 'active' },
// '1': { id: 'profile_name_2', profileStatus: 'inactive' }
// }
I have an array of objects like this:
const data = [{
_id:"49847444033",
name:"yoko"
},{
_id:"49847433333",
name:"doira"
}]
I have to change each item name property to something like this :
...
{
_id:"49847433333",
name:{
en:"John"
}
}
My attempt is to loop object like following :
data.forEach((item) => {
item.name = {en:"john"}
console.log(item)
})
But this always console the original item and the name property value is not modified.
const newData = data.map(user => ({ _id: user._id, name: { en: user.name } }))
I created a library to express transformations like this very simply.
const { pipe, fork, get } = require('rubico')
const data =
[ { _id: '49847444033', name: 'yoko'}
, { _id: '49847433333', name: 'doira'}
]
const onData = pipe([
fork({
_id: get('_id'), // data => data._id
name: fork({ en: get('name') }), // data => ({ en: data.name })
}),
console.log,
])
data.map(onData) /*
{ _id: '49847444033', name: { en: 'yoko' } }
{ _id: '49847433333', name: { en: 'doira' } }
*/
I've commented the code above, but to really understand rubico and get started using it, I recommend you read the intuition and then the docs
try somthing like:
const newList = data.map(obj => {
return { _id: obj._id, name: { en: obj.name } }
});
and the newList list is your new data list so you can do it:
data = newList;
EDIT:
if you have more properties you can change the return line to:
return { ...obj, name: { en: obj.name } }
what will happen here, it will deploy all the object properties as they are, and modify the name property, unfortunately, every property you want to modify, you have to re-write it.
How would I update a title of the specific id with hooks state setup. Here:
const NotesContainer = ({
}) => {
const [notesDummyData, setNotesDummyData] = useState([
{
id: '5',
title: 'Sauna',
},
{
id: '7',
title: 'Finland',
},
]);
const onChangeItemName = (newTitle, oldTitle, itemId) => {
//Update a new title here for id 7
};
Could not find any example for setState hooks.
Just map through the items and if the id is equal to the selected id you modify only the value:
const onChangeItemName = (newTitle, oldTitle, itemId) => {
setNotesDummyData(notesDummyData.map(x => {
if(x.id !== itemId) return x
return {...x, title: newTitle}
}))
}
You can use Array.map(). For each item check if the id is equal to itemId. If it this, spread the item, and replace the title. If not, return the original item:
const onChangeItemName = (title, itemId) => {
setNotesDummyData(notesDummyData.map(o => o.id === itemId ? ({
...o,
title
}) : o));
};
It's easy to update data using React Hook, but there is not working setState(), so there will be working [notThis, thisOne(setNotesDummyDate)] to update your data.
const [notesDummyData, setNotesDummyData] = useState([
{
id: '5',
title: 'Sauna',
},
{
id: '7',
title: 'Finland',
},
]);
Using React Hook method to Update data:
const onChangeItemName = (newTitle, oldTitle, itemId) => {
setNotesDummyDate = useState([
{
id: itemId, // Update
title: newTitle,
},
{
id: itemId, // Update
title: newTitle,
},
]);
}
Still Curious, study here about useState()
Cheer you!