Create a select option in the react js from an object - javascript

I am new to the react-redux. I actually know this question is a very basic question,
Here, I have an object which is like,
questionsCount : [ {
Id : "CSS"
count: "1",
level:"Easy",
type: Non_code},{
Id : "CSS"
count: "2",
level:"Medium",
type: code},
{
Id : "CSS"
count: "5",
level:"Tough",
type: code},
{
Id : "java"
count: "2",
level:"Tough",
type: Non-code},
{
Id : "Html"
count: "4",
level:"Easy",
type: code},]
Now,I have one select drop-down where I want to create an options , So I tried
return this.state.questionsCount.map((item) =>
<option key={item.Id}>{item.Id}</option>
);
In the props I get the level type.
Now, Here what its creating all the option elements with repetative Id's.
Now, What I want to do is that,
the option element will be like, first it should have only provided level elements meanes,
css code:0,Non_code:1
So,Currently Its getting duplicated .
Its getting duplicated because Id is getting repeated. Can any one help me with this ? Thanks
Here,I have that object. Now In that object there are multiple objects which has Id and count and level and type .
Now, from this objects I want to create the select options from this.
It has three diff levels.
expected Output would be like ,
It will be having only easy level
<option>Css code:0,non_code-1></option>
<option>Html code:4,non_code-0></option>
for tough options,
<option>Css code:5,non_code-1></option>
<option>java code:0,non_code-2></option>
same for medium.and tough.
One technology can have code type or non code type questions of type easy or medium or tough. So, I want to create the drop-down of that technolgy depends upon the levels.
If code or non-code not present then it will have 0 for that.

From what I understand in your case, you wish to create a select dropdown based on the difficulty level. To achieve that, you would need to filter our the question based on difficult first before rendering like
processQuestions(questionsCount, difficulty) {
const res = questionsCount.filter(item => item.level === difficulty);
return res.reduce((acc, item) => {
if (acc[item.Id]) {
acc[item.Id] = { ...acc[item.Id], [item.type]: acc[item.Id][item.type]? acc[item.Id][item.type] + 1 : 1};
} else {
acc[item.Id] = { [item.type]: 1};
}
return acc;
}, {})
}
render() {
const { difficulty } = this.props;
const questionsData = this.processQuestions(this.state.questionCount, difficulty);
return Object.entries(questionsData).map(([questionId, data]) => {
return (
<option key={questionId}>{questionId} code: {data.code} non_code: {data['Non-code']}</option>
)
})
}

Related

How to load data in Ant Design Cascader with two level deep options which load lazily?

I am trying to use the Ant design cascader with expanded sub menu on hover, and because there is a lot of data in the sub menu, I only load them lazily as also potrayed in the ant design cascader website.
My cascader consists of 3 different 'lists' of data. I first load something called flows which themselves have a property item which contains either item_id or items_group_id. Items and items-group are themselves different lists of data. The most important aspect of these we need to know is items and items-group have a label, and a value, which are the text name and the unique ID. Flows are lists with additional data and also always have a list of either a few items or item groups or both. Example of each type coming from the backend:
sampleflow = [
{
"id": 13206,
"rate": 23,
"quantity": 23,
"tax": 5,
"amount": 23,
"flow": 163, // NOTE this id is same as the id of the flow
"items_group": null,
"items": 198,
"item": [
163,
198
]
}
]
sampleItem = [
{
"kit_id": null,
"product_id": {
"id": 198,
"name": "Sample Item"
}
},
{
"kit_id": {
"id": 1,
"name": "Item group random1"
},
"product_id": null
}
]
As you can see, item and itemgroup list only has the data id and name, and I have to figure out myself what type of item it is by seeing which id is being sent; either product_id or kit_id(kit and items-group are the same thing).
Note how backend is sendint he flow id which is the same as the id of the flow itself, this is because when I created this record, the frontend sent the data in the format of { name, value, type }
<Form.List name="items">
{(fields, { add, remove }) => { // code to make multiple of these cascaders
return (
<div>
{fields.map((field, index) => (
<>
<Row align="middle">
<Col span={9}>
<div>
<Form.Item name="item">
<Col>
<Cascader
expandTrigger="hover"
defaultValue={cascaderItemValue[0][index] || []}
// defaultValue={fakeCascaderData}
loadData={loadData}
options={options}
onChange={(e, value) => onChangeCascader(e, index, value)}
placeholder="Select"
changeOnSelect
/>
</Col>
</Form.Item>
</div>
</Col></row></div></Form.List>
....
const loadData = async (selectedOptions) => {
const targetOption = selectedOptions[selectedOptions.length - 1];
const flowItems = await loadAPI(`flows-exp/?id=${selectedOptions[0].value}`);
if (flowItems) {
targetOption.children = flowItems.data.items.map((item) => ({
value: item.kit_id ? item.kit_id.id : item.product_id.id,
label: item.kit_id ? `Item-Group ${item.kit_id.name}` : `Item ${item.product_id.name}`,
type: item.kit_id ? `Item-Group` : `Item `,
}));
}
setOptions([...options]);
};
As you can see I also have it in a function that makes multiple of these according to the user's choice. That added a bit of complexity of indexing every form item else the backend won't accept the data properly nor the frontend will be able to load them in the correct order. Anyways I was able to do this perfectly with a single level dept cascader. I am trying the same concept for this, but the second level depth is making it impossible for me to load the data properly.
const onChangeCascader = (array, index, val) => {
console.log('array, index', array, index, val);
if (array[0] && array[1] && val[1]) {
const name = array[0];
const value = array[1];
const type = val[1]?.type;
setItemsSelectedOptions((prev) => ({ ...prev, [String(index)]: { name, value, type } }));
}
};
Here I am sending the data to backend using this format of { name, value, type } where the name is the flow ID, value is product select id, and because there are two types of products, one item and other item-group, i also need to send which kind it is either item or item-group. ex response: { 192, 1, 'Item'}
Basically it is an amalgamation of the features shown. I was able to load the data from my backend, and show the options perfectly. Then i formatted the data a bit before sending it back to my backend. Here is the fucntion where i format the data coming from the backend so the cascader element can load the data properly:
useEffect(() => {
const fetchData = async (id) => {
const Rawdata = await retrieveAllotmentbyid(allotmentid);
console.log('Rawdata', Rawdata);
if (Rawdata.data.flows) {
responseProductArray = Rawdata.data.flows.map((product) => ({
product_type: product.flow || '',
product_value: product.items || product.items_group,
}));
}
const rawdataflowitems = []
const newselectedOptions = []
for (let i = 0; i < Rawdata.data.flows.length; i++) {
rawdataflowitems[i] = await Promise.all([loadAPI(`flows-exp/?id=${Rawdata.data.flows[i].flow}`)]);
}
console.log('rawdataflowitems', rawdataflowitems);
responseProductArray.map((prod) => {
tempProductArray.push([(prod.product_type), prod.product_value])
})
console.log('responseProductArray', responseProductArray, tempProductArray);
const { data } = Rawdata;
if (data.flows) {
data.items = data.flows;
}
for (let i = 0; i < data.items.length; i++) {
data.items[i].item = tempProductArray[i]
}
const cascaderItemArray = []
if (data.items) {
for (let i = 0; i < data.items.length; i++) {
if (data.items[i].items) {
cascaderItemArray[i] = ['product', data.items[i].items];
onChangeCascader(cascaderItemArray[i], i, 'items')
setCascaderItemValue([...cascaderItemValue, cascaderItemArray]);
} else {
cascaderItemArray[i] = ['kit', data.items[i].items_group];
onChangeCascader(cascaderItemArray[i], i, 'items_group')
setCascaderItemValue([...cascaderItemValue, cascaderItemArray]);
}
}
}
console.log('cleaned data after fetching', data);
console.log('cascaderItemValue', cascaderItemValue);
form.setFieldsValue({
...data,
});
}
if (allotmentid) {
fetchData(allotmentid);
}
}, [allotmentid])
In the fetchdata, there is an api call to the backend which loads the data of what items each of the flow sent from the backend contain. It is impossible for me to load every item in every flow as there are 100s of flows with around 5 items in each. So i only load the data of the flows I am getting from the backend. But the issue is, i am unable to load this data into the options state which i use as the options for the cascader. When a user manually uses the cascader, and hovers over the options, i am able to load the data from the backend and update the options which is a state. What I basically do when a user manually hovers over the cascader items, I take the value of the hovered flow, then make an api call to the backend and load the items data and format them properly. Then I add that to the children of the option which was hoveredd using the onChangeCascader i have mentioned above. I believe this is the issue I am having. After literally spending two shifts of 8 hours, i am very clueless on how to do this, or even if this apporach is correct.
This is how create the initial options for the cascader made up of only flows data:
useEffect(() => {
let flowOpts = [];
if (flows) {
flowOpts = flows.map((flow) => ({
value: flow.id,
label: flow.flow_name,
isLeaf: false,
}));
}
if (options.length == 0) {
setOptions(flowOpts);
}
}, [flows]);
After hovering, the children part is loaded and the items or item-groups are selectable and this is how the options look like:
{
"value": 163,
"label": "Rajah Garner",
"isLeaf": false,
"children": [
{
"value": 198,
"label": "Item 0",
"type": "Item "
},
{
"value": 1,
"label": "Item-Group 78465",
"type": "Item-Group"
}
]
}
Safe to say I have used atleast 100 console logs in this single file and am trying to track the data and its format in every way, but still I am helpless on how to approach this.
I understand this is an obscure and long problem, but i was unable to find anything similar on google or even SO. I even messaged the author of the cascader element from ant design to no avail. Please let me know what else details is needed to atleast discuss this.

React json list

I hope I can explain the question clearly. I need to create a few categories in category with <input type="checkbox"/>. Can you help how do it
{
"properties":{
"category":[
"0" : "category-1",
"1" : "category-2"
],
"image": "https://link...",
...
}
}
now I can only add one value at a time, but I need a lot
{
"properties":{
"category": "category-1",
"image": "https://link...",
...
}
}
const handleSubmit = (e) =>{
e.preventDefault();
const movie = {id, category, title, poster, rating, year, video, trailer, description};
fetch('http://localhost:8000/movies', {
method: 'POST',
headers: {"Content-Type" : "application/json" },
body: JSON.stringify(movie)
}).then(() => {
alert('Успешно добавился фильм!');
})
}
So if im understanding you correctly, you want to add multiple categories to the body of a POST endpoint? As long as your api handles an array for the “category”, then its pretty easy! But first, there are some things I see in your code:
In javascript, you don’t explicitly write the index of an array. You just write the item, for
example

const listOfStrings = [“string 1”, “string 2”]
const listOfObj = [{name: ‘Aj”}, {name: ‘bj’}]
It seems like you are implicitly passing in the properties for your “movie” object, just make sure that each property is defined somewhere above.
Now on to your question! What you want to do is the following:
Create a list of categories, make sure they match whatever the backend is expecting
create a state to track the selected categories
map through the array and render an input for each
assign each input props based on its indexed category
create a function that updates the selected state with a new category or a category removed
The key principles you'll need to research if youre unfamiliar with this are:
Javascript: map, filter
React: JSX,
Rendering lists
hooks (useState)
Code Example: https://codesandbox.io/s/jolly-moon-fbhs7c?file=/src/App.js

filtering list of objects based on multi-selection dropdowns Javascript/Typescript/Lodash/Angular

I fot a bit of a complex issue on my hands that I would need your help.
I have multiple dropdown filters like location, category, subcategory e.t.c. My initial version is working where which ever combination is chosen, it will return the right result. My next challenge is to make the dropdowns with multi select. I am using firebase for this, trying to do a complex filtering on the client side.
I have list of objects like this that I get from the DB:
{
data1: {
status: true,
location: "New York",
category: "Food",
subcategory: "Pizza",
price: 24
}
data2: {
status: true,
location: "Chicago",
category: "Food",
subcategory: "Hot Dogs",
price: 5
}
data3: {
status: true,
location: "Miami",
category: "Food",
subcategory: "Taco",
price: 2
}
}
In order this to filter by multiple values I have the following:
filter() {
this.filteredData = _.filter(this.getListings, _.conforms(this.activeFilters)).filter(x =>
x.status === true);
}
Then, I have a method that sets the active filters based on a condition or show all from that property by removing that active filter, for example:
filterLocation() {
const location = this.filtersData.get('location').value;
this.locations = [];
for(let i = 0; i < location.length; i++) {
if (location[i].itemName === 'All') {
this.removeFilter('location');
}
if (location[i].itemName !== 'All') {
this.locations.push(location[i].itemName);
property = 'location';
this.activeFilters[property] = val => this.locations.some(x =>
val.includes(x));
this.filter();
}
}
}
And then, I have the same or similar method for category, subcategory e.t.c.
The thing I want to achieve now is for example I want to multi-select locations and categories or subcategories if needed but not to be limited to adding more properties in the future.
So, if I choose New York and Miami I want to get all items that contain those values but not to be limited if I want to filter by additional values like food, drink e.t.c.
This example works perfectly for filtering by single value, you can add up as many filters and combinations as you like, it will always return an array of objects matching what you selected from the dropdowns.
I am trying some stuff out, Ill update the question if I manage to solve it, in the meantime I appreciate all the help. Thanks.
I figured it out! I updated the filterLocation() method according to my solution. I am going to work on improving the filter now.

Update multiple rows in sequelize with different conditions

I'm trying to perform an update command with sequelize on rows in a postgres database. I need to be able to update multiple rows that have different conditions with the same value.
For example, assume I have a user table that contains the following fields:
ID
First Name
Last Name
Gender
Location
createdAt
Assume, I have 4 records in this table, I want to update records with ID - 1 and 4 with a new location say Nigeria.
Something like this: SET field1 = 'foo' WHERE id = 1, SET field1 = 'bar' WHERE id = 2
How can I achieve that with sequelize?
You can update multiple record at a time , but same updates for all records
, if you want to make different updates for different conditons then you have to run that multiple time
Example :
This will update fields1 to foo , where id is 1 or 4
let ids = [1,4];
Your_model.update({ field1 : 'foo' },{ where : { id : ids }});
This will update field1 to foo if id is 1 , and field1 to bar if id is 4
Your_model.update({ field1 : 'foo' },{ where : { id : 1 }});
Your_model.update({ field1 : 'bar' },{ where : { id : 4 }});
Hope this will clear all your doubts.
You can update multiple rows following your conditions, and to do that the operators are very helpful.
Look here: http://docs.sequelizejs.com/manual/querying.html (operators)
const { Op } = Sequelize;
DisplayMedia.update(
{
field: 'bar'
},
{
where: {
id: {
[Op.in]: [1, 10, 15, ..] // this will update all the records
} // with an id from the list
}
}
)
There is all kinds of operators, including the range operators, or like operator ...etc
Also one of the important questions when it come to update, is how to update all rows?
Not including where results in an error "Missing where attribute in the options parameter passed to update".
The answer is in the code bellow: provide a where with an empty object.
await DisplayMediaSequence.update({
default: false
}, {
where: {}, // <-- here
transaction
});
await DisplayMediaSequence.update({
default: true <-- after all turned to false, we now set the new default. (that to show a practical expample) -->
}, {
where: {
id
},
transaction
});
we planning to save different values for same fields in multiple row there is a possible for getting all field values are same in database.
using for loop
const {idArray,group_id} = params;
for(const item of idArray){
const response = await Your_model.findOne({ where:{group_id,user_id:null}, order: [['id', 'DESC']] });
await response.update({user_id:item});
}

On/off toggle for filtering content React

This React code is filtering variables according to the "tag" which it contains (as seen in the list array).
However, I cannot toggle the filter variables (tags) on/off.
I want to be able to turn certain filters on/off, and have just those filters apply.
How is this achieved?
My entire code is in this codepen (
http://codepen.io/yarnball/pen/GqbyWr?editors=1010)
I believe I have to some how add it to the array on line 79 (below), but I have not had success with this
Line 79:
selectTag: function (tag) {
this.setState({
displayedCategories: this.state.displayedCategories.concat([tag]),
$push : [newObject]
});
},
My data looks like this:
"title": "Into the Wild",
"tag": [
{
"name": "Movie",
"taglevel": 1,
"id": 1
},
{
"name": "Adventure",
"taglevel": 2,
"id": 30
},
{
"name": "Book",
"taglevel": 1,
"id": 2
}
],
"info": []
}
In order to toggle the filters, you will need to check for the existence of the tag in the existing displayedCategories, look through the array for the tag, and then either remove it or add it in.
It is normally my preference to try to be functional so that assignment cannot cause confusion, so I will use a mostly functional style.
First to check for the presence of the tag we can use a filter operation.
var filteredCategories = this.state.displayedCategories
.filter(function (existingTag) {
return existingTag.taglevel !== tag.taglevel ||
existingTag.id !== tag.id;
});
So we now have a list of tags that are filtered to only include those that don't match the passed tag. We can check if the filtered list is the same size as the old list to see if we removed one. Alternatively, we could have filtered the other way around to see if we needed to remove one using some.
if (filteredCategories.length === this.state.displayedCategories.length){
// tag wasn't present, add it
} else {
// tag was present, use filtered list.
}
As I said above, I prefer functional, so we can do it slightly differently:
var newCategories = filteredCategories.length === this.state.displayedCategories.length ?
filteredCategories.concat([tag]) :
filteredCategories;
and then we need to set state:
this.setState({
displayedCategories: newCategories,
});
To combine those together:
var filteredCategories = this.state.displayedCategories
.filter(function (existingTag) {
return existingTag.taglevel !== tag.taglevel ||
existingTag.id !== tag.id;
});
var newCategories = filteredCategories.length === this.state.displayedCategories.length ?
filteredCategories.concat([tag]) :
filteredCategories;
this.setState({
displayedCategories: newCategories,
});

Categories