Join multiple array maps in ReactJs - javascript

im new in reactjs, is that possible to do in reactjs,like mysql inner join, here my sample code.
{dataCustomer.map((customer) => (
<tr>
<td>{customer.custid}</td>
<td>{customer.custname}</td>
<td>{customer.mailingaddr}</td>
<td>{customer.stateid}</td>
<td>{customer.districtid}</td>
<td>{customer.postcode}</td>
</tr>
))}
{dataState.map((state) => (
<tr>
<td>{state.stateid}</td>
<td>{state.statename}</td>
</tr>
))}
how to join array map data from customer.stateid & state.stateid to call state.statename without use SQL syntax?..Is that possible?

This should work
let joinedData=[]
dataCustomer.forEach((customer)=>{
let st= dataState.filter((state)=>state.stateid===customer.stateid);
if(st.length>0)
joinedData.push({...customer,statename:st[0].statename})
})
joinedData array will now contain the customer objects with the corresponding statename and you can use it as
{joinedData.map((customer) => (
<tr>
<td>{customer.custid}</td>
<td>{customer.custname}</td>
<td>{customer.mailingaddr}</td>
<td>{customer.stateid}</td>
<td>{customer.districtid}</td>
<td>{customer.postcode}</td>
<td>{customer.statename}</td>
</tr>
))}

It is not exactly the same but I think the function below that I wrote can help you:
let customers = [{
name: "Foo",
stateid: 1
},
{
name: "Boo",
stateid: 3
},
{
name: "Goo",
stateid: 2
},
{
name: "Zoo",
stateid: 2
},
];
let states = [{
name: "State1",
id: 1
},
{
name: "State2",
id: 2
},
];
function join(customers, states, column1, column2) {
return customers.map(customer => {
states.forEach(state => {
if (customer[column1] === state[column2]) {
customer["state"] = { ...state };
}
})
return customer;
})
}
console.log(join(customers, states, "stateid", "id"))
Note that column1 and column2 parameters are the properties you are joining on.

Related

React: Filter table data with multiple column values

I have the following an array object data. I wanted to filter it's data when a user provide either title, category or published values from an input. I can only filter the data only with title value. How can I make it to category and published values as well? here is my code. `
const data = [
{ id: 1, title: "Hunger games 2", category: "Action", published: "2013" },
{ id: 2, title: "Iron Man", category: "Action", published: "2013" },
];
const [searchValue, setSearchValue] = useState(""); //searchValue is an input value
const DisplayData = data
?.filter((row) => row?.title?.match(new RegExp(searchValue, "i")))
?.map((items) => {
return (
<>
<tr key={items.id}>
<td className="text-center">{items.title}</td>
<td>{items.category}</td>
<td>{items.published}</td>
</tr>
</>
);
});
You can add "or" conditions to your filter:
const DisplayData = data
?.filter((row) => row?.title?.match(new RegExp(searchValue, "I")) ||
row?.category?.match(new RegExp(searchValue, "I")) ||
row?.published?.match(new RegExp(searchValue, "I"))
)
?.map((items) => ...

Vue v-for loop - How To Target Component When Array is Filtered

I am using a computed value to dynamically filter an array ("orders").
The computed .filter() function allows the user to dynamically search by order number, name or reference:
data() {
return {
orders: [],
search: "" // search string from a text input
};
},
computed: {
filtered:
return this.orders.filter(order => {
const s =
order.order_number + order.reference + order.name;
const su = s.toUpperCase();
return su.match(this.search.toUpperCase());
});
}
I am using a v-for loop to render the search results as follows:
<tbody v-for="(order, index) in filtered" :key="order.id">
<tr>
<td #click="add_events(order, index)>{{order.order_number}}</td>
<td>{{order.reference}}</td>
<td>{{order.name}}</td>
...
</tr>
</tbody>
I want to use the #click to target a specific component (an object) in the filtered array and use $set to append a value ("objEvents") to that object:
methods: {
add_events (order, index) {
const objEvents= [ external data from an API ]
this.$set(this.orders[index], "events", objEvents)
}
}
However the index of the component in the filtered array ("filtered") is not the same as its index in the original array ("orders") and so the add_events method targets the wrong component.
Can I use key to target the correct component? or is there some other way to identify the target component in the filtered array?
There's no need to track index. filtered is just an array of references to the original objects in orders, so you could modify the order iterator in add_events() to achieve the desired effect:
this.$set(order, 'events', objEvents);
new Vue({
el: '#app',
data() {
return {
orders: [
{id: 1, order_number: 111, name: 'John', reference: 'R111'},
{id: 2, order_number: 222, name: 'Bob', reference: 'R222'},
{id: 3, order_number: 333, name: 'Bob', reference: 'R333'},
],
search: ''
};
},
computed: {
filtered() {
return this.orders.filter(order => {
const s =
order.order_number + order.reference + order.name;
const su = s.toUpperCase();
return su.match(this.search.toUpperCase());
});
}
},
methods: {
add_events(order, index) {
const objEvents = [
{id: 1, name: 'Event 1'},
{id: 2, name: 'Event 2'},
{id: 3, name: 'Event 3'}
];
this.$set(order, "events", objEvents);
}
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<input type="text" v-model="search" placeholder="Search">
<table>
<tbody v-for="(order, index) in filtered" :key="order.id">
<tr>
<td #click="add_events(order, index)">{{order.order_number}}</td>
<td>{{order.reference}}</td>
<td>{{order.name}}</td>
<td>{{order.events}}</td>
</tr>
</tbody>
</table>
<pre>{{orders}}</pre>
</div>
You could map the original array and add the an origIndex property to each item as follows :
computed:{
filtered(){
let mapped= this.orders.map((item,i)=>{
let tmp=item;
tmp.origIndex=i;
return tmp;
});
return this.mapped.filter(order => {
const s =
order.order_number + order.reference + order.name;
const su = s.toUpperCase();
return su.match(this.search.toUpperCase());
});
}
}//end computed
In your template use the origIndex property instead of index
<tbody v-for="(order, index) in filtered" :key="order.id">
<tr>
<td #click="add_events(order, order.origIndex)>{{order.order_number}}</td>
<td>{{order.reference}}</td>
<td>{{order.name}}</td>
...
</tr>
</tbody>

Display array list of object in React JS

Hi I have this list array of object in react js and I don't know how to display in my render view. Anyone can give an idea on how to do it?
Post:{
Store1: [
0:{Id:"0001", Business:"Ministop"}
]
Store2: [{
0:{Id:"0002", Business:"Grocery Store"}
}]
Store3: [
0:{Id:"0003", Business:"Seven Eleven"}
]
Store4: [
0:{Id:"0004", Business:"Big Store"},
1:{Id:"0005", Business:"Medium Store"}
]
}
This is the sample output:
**Store 1**
**Id Business**
0001 Ministop
**Store 2**
**Id Business**
0002 Grocery Store
**Store 3**
**Id Business**
0003 Seven Eleven
**Store 4**
**Id Business**
0004 Big Store
0005 Medium Store
I have this code and I've got an error this.state.post.map is not a function
render() {
const groupList = this.state.post.map((data, index) => {
return (
<div key={index}>
<div>{data}</div>
</div>
)
});
return (
<div>{groupList}</div>
)
}
Thank you
This is how you map it. just change post with this.state.post
const post = {
Store1: [
{ Id: '0001', Business: 'Ministop' }
],
Store2: [
{ Id: '0002', Business: 'Grocery Store' }
],
Store3: [
{ Id: '0003', Business: 'Seven Eleven' }
],
Store4: [
{ Id: '0004', Business: 'Big Store' },
{ Id: '0005', Business: 'Medium Store' }
]
};
console.log(Object.keys(post).reduce((acccumilator, iterator) => {
return [...acccumilator, ...post[iterator]];
}, []));
/*
Object.keys(this.state.post).reduce((acccumilator, iterator) => {
return [...acccumilator, ...post[iterator]];
}, []).map(data => {
return (
<div key={data.id}>
<div>{data.Business}</div>
</div>
)
})
*/
map is not a method of an object. You can map over its keys using Object.keys.
render() {
const groupList = Object.keys(this.state.post).map((key) => {
return (
<div key={key}>
<div>{this.state.post[key]}</div>
</div>
)
});
return (
<div>{groupList}</div>
)
}
However, there are other problems once you fix that but you should try to solve them yourself and ask other questions if you can't

Using map pushes new items to the end of the array rather than pushing a new array with updated values

I have a list of items that users can click to add an item to their array. Rather than updating the value in the array, it is pushing a new value with the same number. I am getting map from Lodash FP.
This is what I am using to map through:
{map((item) => (<Item {...item} key={btoa(Math.random()).substring(0, 12)} />), items)}
If I am to click on an item in the array, the result I would get is:
0: {id: "item1", quantity: 1}
1: {id: "item1", quantity: 1}
Yet the result I would expect from this is:
0: {id: "item1", quantity: 2}
Implementation:
Component that allows you to add an item:
const Product = ({add, id, title, image}) => (
<div className={styles.product} onClick={() => add(id)}>
<img src={image} alt={title} className={styles.productImage}/>
{title}
</div>
);
export default connect(() => ({}), {add})(Product);`
Component that loops through the results:
const Cart = connect(
() => ({}),
{clear}
)(({items, clear, total}) => {
return (
<div>
<Heading><FontAwesomeIcon icon={faShoppingCart} /> Cart</Heading>
{items.length ? <button onClick={clear}>Clear all items</button> : null }
<table>
<thead>
<tr>
<th>Product</th>
<th>Price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{/* The original version, with a randomly generated key */}
{items.length ? map((item) =>
(<Item {...item} key={btoa(Math.random()).substring(0, 12)} />),
items) : <tr><td>Your cart is empty!</td></tr>}
</tbody>
</table>
{items.length ? <div className={styles.total}>${total}</div> : null }
</div>);
});
export default connect((state) => {
return {
items: state.cart.items,
total: reduce(
(sum, {id, quantity}) => sum + products[id].price * quantity,
0,
state.cart.items
).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'),
};
})(Cart);
Action that is being called:
[ADD_ITEM]: (state, {payload: id}) => ({
...state,
items: [
...state.items,
{id, quantity: 1},
],
}),
If you want to update state via id, then you'll want to map through the items array and find the matching id to update the matching quantity. The example below utilizes React state, but is no different for redux reducer state (return {...state, items: state.items.map(...etc)}).
Working example: https://codesandbox.io/s/rjmx8vw99p
import React, { Component } from "react";
export default class App extends Component {
state = {
items: [
{ id: "Apples", quantity: 1 },
{ id: "Strawberries", quantity: 1 },
{ id: "Grapes", quantity: 1 },
{ id: "Apricots", quantity: 1 }
]
};
handleClick = id => {
this.setState(prevState => ({
// ...prevState (not needed for this example, but needed for redux)
items: prevState.items.map(
item =>
id === item.id
? { id, quantity: item.quantity + 1 }
: { ...item }
)
}));
};
render = () => (
<div className="container">
<h1>Updating Values Inside Array</h1>
{this.state.items.map(({ id, quantity }) => (
<button
style={{ marginRight: 10 }}
className="uk-button uk-button-primary"
key={id}
onClick={() => this.handleClick(id)}
>
{id} ({quantity})
</button>
))}
</div>
);
}
What's happening in your code above is simply appending the array with a new object:
items: [
{ id: "item1", quantity: 1 }, // ...spread out previous objects in array
{ id: "item2", quantity: 1 },
{ id: "item3", quantity: 1 },
{ id: "item4", quantity: 1 },
{ id: "item1", quantity: 1 } // add another object
]
Also, this:
export default connect(() => ({}), {add})(Product);
should be this:
export default connect(null, {add})(Product);

Make a Tree view from JSON data using React JS

First of all i am very new to React JS. So that i am writing this question. I am trying this for three days.
What I have to do, make a list of category, like-
Category1
->Sub-Category1
->Sub-Category2
Categroy2
Category3
.
.
.
CategoryN
And I have this json data to make the listing
[
{
Id: 1,
Name: "Category1",
ParentId: 0,
},
{
Id: 5,
Name: "Sub-Category1",
ParentId: 1,
},
{
Id: 23,
Name: "Sub-Category2",
ParentId: 1,
},
{
Id: 50,
Name: "Category2",
ParentId: 0,
},
{
Id: 54,
Name: "Category3",
ParentId: 0,
},
];
I have tried many open source examples, but their json data format is not like mine. so that that are not useful for me. I have build something but that is not like my expected result. Here is my jsfiddle link what i have done.
https://jsfiddle.net/mrahman_cse/6wwan1fn/
Note: Every subcategory will goes under a category depend on "ParentId",If any one have "ParentId":0 then, it is actually a category, not subcategory. please see the JSON
Thanks in advance.
You can use this code jsfiddle
This example allows to add new nested categories, and do nested searching.
code with comments:
var SearchExample = React.createClass({
getInitialState: function() {
return {
searchString: ''
};
},
handleChange: function(e) {
this.setState({
searchString: e.target.value.trim().toLowerCase()
});
},
isMatch(e,searchString){
return e.Name.toLowerCase().match(searchString)
},
nestingSerch(e,searchString){
//recursive searching nesting
return this.isMatch(e,searchString) || (e.subcats.length && e.subcats.some(e=>this.nestingSerch(e,searchString)));
},
renderCat(cat){
//recursive rendering
return (
<li key={cat.Id}> {cat.Name}
{(cat.subcats && cat.subcats.length) ? <ul>{cat.subcats.map(this.renderCat)}</ul>:""}
</li>);
},
render() {
let {items} = this.props;
let {searchString} = this.state;
//filtering cattegories
if (searchString.length) {
items = items.filter(e=>this.nestingSerch(e,searchString))
console.log(items);
};
//nesting, adding to cattegories their subcatigories
items.forEach(e=>e.subcats=items.filter(el=>el.ParentId==e.Id));
//filter root categories
items=items.filter(e=>e.ParentId==0);
//filter root categories
return (
<div>
<input onChange={this.handleChange} placeholder="Type here" type="text" value={this.state.searchString}/>
<ul>{items.map(this.renderCat)}</ul>
</div>
);
}
});

Categories