Map array object inside map - ReactJS - javascript

I am planning to map each item in the object (contact numbers) for every Person
Putting it inside and seperate them in comma ','
When I use data.contact_number, output is combined all fields in array.
const ContactList = (props) => (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Contact Numbers</th>
<th>Address</th>
<th>Email</th>
<th>Note</th>
</tr>
</thead>
<tbody>
{props.data.map(data =>
<tr key={data.id}>
<td>{data.name}</td>
{props.data[data.id].contact_number.map(cn =>
<td>{cn}</td>
)}
<td>{data.address}</td>
<td>{data.email}</td>
<td>{data.note}</td>
</tr>
)}
</tbody>
</table>
</div>
)
This is my data:
{
"id": 7,
"name": "sd",
"email": "ajot#qwe.com",
"address": "testAddress",
"note": "testNote",
"contact_number": [
"11",
"12",
"31",
"41",
"51",
"61"
]
}
Error :
Uncaught (in promise) TypeError: Cannot read property 'contact_number'
of undefined

Try this:
const ContactList = (props) => (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Contact Numbers</th>
<th>Address</th>
<th>Email</th>
<th>Note</th>
</tr>
</thead>
<tbody>
{props.data.map(data =>
<tr key={data.id}>
<td>{data.name}</td>
<td>{data.contact_number.map(cn => cn).join(', ')}</td>
<td>{data.address}</td>
<td>{data.email}</td>
<td>{data.note}</td>
</tr>
)}
</tbody>
</table>
</div>
)
This line which I have changed should give you your desired effect:
{data.contact_number.map(cn => cn).join(', ')} by writing all the contact_number values to a string separated by commas.

Replace this :
{props.data[data.id].contact_number.map(cn =>
<td>{cn}</td>
)}
by this :
{data.contact_number.map(cn =>
<td>{cn}</td>
)}
props.data[data.id] is undefined because props.data[data.id] is not equal to data

The data-path is wrong:
props.data[data.id].contact_number
or the data have to be structured like
[7 : {
"name": "sd",
"email": "ajot#qwe.com",
"address": "testAddress",
"note": "testNote",
"contact_number": [
"11",
"12"
]
},
8 : { ... },
0 : { ... }
]

You need to parse your json.
JSON.parse(yourJson) turns the data into a JavaScript object.
JSON.parse(props.data).map(data => ...

If you see properly data is not an array so you can't use map on that. You can simply choose this.
const ContactList = (props) => (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Contact Numbers</th>
<th>Address</th>
<th>Email</th>
<th>Note</th>
</tr>
</thead>
<tbody>
<tr key={this.props.data.id}>
<td>{this.props.data.name}</td>
{this.props.data.contact_number.map((contact_number)=>{
<td>{contact_number}</td>
})}
</tr>
</tbody>
</table>
</div>
)

Related

Rendering an object into a table in React

I am a React beginner and I am having trouble with rendering an object into a table. I can access the ctx object with console.log but I cannot display it on the browser in the table.
If anyone can help me please give me your advice. the code is below.
The goal is to display data from the object(ctx) into the table.
function AllData(){
const ctx = {users:[{name:'john', email:'john#email.com', passwords:'password'},{name:'smith', email:'smith#email.com', passwords:'password']};
const userdata = ctx.users.map((user)=>{
(
<tr>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
</tr>
)
});
return (
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Password</th>
</tr>
</thead>
<tbody>
{userdata}
</tbody>
</table>
);
}
You need to return something from the .map like
const userdata = ctx.users.map((user) => {
return (
<tr key={user.name}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
</tr>
)
});
Or even just
const userdata = ctx.users.map((user) => (
<tr key={user.name}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
</tr>
));
Another option would be like
return (
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Password</th>
</tr>
</thead>
<tbody>
{
ctx.users.map((user) => (
<tr key={user.name}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
</tr>
))
}
</tbody>
</table>
)
Also added the key property, since you are using an array.
Add return inside map
const userdata = ctx.users.map((user)=>{
return (
<tr>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
</tr>
)
});
There are a couple of issues with your code, the main one being that the function that you use in the .map does not return anything.
Other issues:
Missing } in the definition of ctx.
Mismatch in property name: passwords vs password.
No key property present in the JSX elements that are returned by the map function.
Below is a runnable sample with all these issues fixed.
function AllData() {
const ctx = {
users: [
{ name: 'john', email: 'john#email.com', password: 'password' },
{ name: 'smith', email: 'smith#email.com', password: 'password' }
]
};
const userdata = ctx.users.map((user)=>{
return (
<tr key={user.name}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
</tr>
)
});
return (
<table className="table">
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Password</th>
</tr>
</thead>
<tbody>
{userdata}
</tbody>
</table>
)
}
ReactDOM.render(<AllData />, document.getElementById('react'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How can I determine which checkbox is checked?

<table>
<tbody>
<tr>
<th>Select</th>
<th>User Id</th>
<th>Id</th>
<th>Is Banned?</th>
<th>registration_date</th>
</tr>
{data.map((item, i) => (
<tr key={i}>
<td><input type="checkbox" checked={isChecked} /></td>
<td>{item.user_id}</td>
<td>{item.user_name}</td>
<td className="isbanned">{item.isbanned}</td>
<td>{item.registration_date}</td>
</tr>
))}
</tbody></table>
this is my code as you see in up. My question is:
How can I detect user_id 1 checbox is checked?
How should I change my code? or what I can use for that?
You can do something like this
const data = [
{
user_id: "some-id",
user_name: "Me",
isbanned: "no",
registration_date: "2000",
},
]
function StackOverflow() {
const [selectedUserIds, setSelectedUserIds] = useState([])
const addOrRemoveId = (id) => {
setSelectedUserIds((state) => {
if (state.includes(id)) {
// If new id exists in current list then we remove it from state
return selectedUserIds.filter((currentId) => currentId !== id)
}
// Else we add the item id to our state
return [...state, id]
})
}
return (
<table>
<tbody>
<tr>
<th>Select</th>
<th>User Id</th>
<th>Id</th>
<th>Is Banned?</th>
<th>registration_date</th>
</tr>
{data.map(({ user_id, ...item }) => (
<tr key={user_id}>
<td>
<input
checked={selectedUserIds.includes(user_id)}
onChange={() => addOrRemoveId(user_id)}
type="checkbox"
/>
</td>
<td>{user_id}</td>
<td>{item.user_name}</td>
<td className="isbanned">{item.isbanned}</td>
<td>{item.registration_date}</td>
</tr>
))}
</tbody>
</table>
)
}
To consider: Never use an index or a combination string of them as component keys. Keys are intended to be unique, if you have an userId already, then use it as that key id

ReactJs Render Value (Array of Objects) of Object

{
"pendingShareholder": [
[{
"id": 5351,
"userName": "iverson",
"firstName": "Allen",
"lastName": "Iverson",
"password": "$2a$10$20ILdapdX6u8G1nH2jIr6upiKY04LCxD9yjHKUHRhUfpuG1w1ywd2",
"contact": "97801671",
"email": "john.doe#gmail.com",
"roles": [{
"id": 3,
"name": "ROLE_SHAREHOLDER"
}]
},
{
"id": 5951,
"userName": "rosgeller",
"firstName": "Ros",
"lastName": "Geller",
"password": "$2a$10$Udrju2Tj6mKGJRZA3d2GFer6kfSI988xI1/R50s.XmrHcIN1IJxoO",
"contact": "90908899",
"email": "peter.sou#gmail.com",
"roles": [{
"id": 3,
"name": "ROLE_SHAREHOLDER"
}]
}
]
]
}
Hi all
I have the above object. As you can see it is an object, with one key ("pendingShareholder"). The value of this key is an array inside an array (with objects inside).
I need to return this out in ReactJS. Using React Hooks here. I can't seem to do it no matter what :(
Can anyone help me. I am going nuts here
Thanks in advance!
const adminStateObject = useSelector((state) => state.admin11111);`
return (
<div className="adminmaincontent">
<h2>Pending Approval Users</h2>
<Table striped bordered hover size="sm" responsive>
<thead>
<tr>
<th>ID</th>
<th>UserName</th>
<th>First Name</th>
<th>Last Name</th>
<th>Contact</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
{Object.keys(adminStateObject).map((key, i) => (
<tbody key={uuid()}>
{adminStateObject[key].map((key2, i2) => (
<tr key={uuid()}>
<td key={uuid()}>{key2.id}</td>
<td key={uuid()}>{key2.userName}</td>
<td key={uuid()}>{key2.firstName}</td>
<td key={uuid()}>{key2.lastName}</td>
<td key={uuid()}>{key2.contact}</td>
<td key={uuid()}>{key2.email}</td>
</tr>
))}
</tbody>
))}
</Table>
</div>
);
It looks like you have too many map operations going on. You need one that iterates over your nested array.
And as Gulam mentions in their comment using uuid on every tbody, tr, and td is overkill. Just add the object id as the row key.
function Example({ data }) {
return (
<table>
<thead>
<tr>
<th>ID</th>
<th>UserName</th>
<th>First Name</th>
<th>Last Name</th>
<th>Contact</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{data.pendingShareholder[0].map(obj => (
<tr key={obj.id}>
<td>{obj.id}</td>
<td>{obj.userName}</td>
<td>{obj.firstName}</td>
<td>{obj.lastName}</td>
<td>{obj.contact}</td>
<td>{obj.email}</td>
</tr>
))}
</tbody>
</table>
);
};
const data = {pendingShareholder:[[{id:5351,userName:"iverson",firstName:"Allen",lastName:"Iverson",password:"$2a$10$20ILdapdX6u8G1nH2jIr6upiKY04LCxD9yjHKUHRhUfpuG1w1ywd2",contact:"97801671",email:"john.doe#gmail.com",roles:[{id:3,name:"ROLE_SHAREHOLDER"}]},{id:5951,userName:"rosgeller",firstName:"Ros",lastName:"Geller",password:"$2a$10$Udrju2Tj6mKGJRZA3d2GFer6kfSI988xI1/R50s.XmrHcIN1IJxoO",contact:"90908899",email:"peter.sou#gmail.com",roles:[{id:3,name:"ROLE_SHAREHOLDER"}]}]]};
// Render it
ReactDOM.render(
<Example data={data} />,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

How can I re-render a view after deleting an object from an array, in Svelte?

I am working on a small Svelte application, for learning purposes (Im new to Svelte). The application uses an array of objects displayed in a view as an HTML table:
let countries = [
{ code: "AF", name: "Afghanistan" },
{ code: "AL", name: "Albania" },
{ code: "IL", name: "Israel" }
];
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>Code</th>
<th>Name</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
{#if countries.length}
{#each countries as c, index}
<tr>
<td>{index+1}</td>
<td>{c.code}</td>
<td>{c.name}</td>
<td class="text-right">
<button data-code="{c.code}" on:click="{deleteCountry}" class="btn btn-sm btn-danger">Delete</button>
</td>
</tr>
{/each}
{:else}
<tr>
<td colspan="4">There are no countries</td>
</tr>
{/if}
</tbody>
</table>
I am doing a delete operation this way:
function deleteCountry(){
let ccode = this.getAttribute('data-code');
let itemIdx = countries.findIndex(x => x.code == ccode);
countries.splice(itemIdx,1);
console.log(countries);
}
There is a REPL here.
The problem
I have been unable to render the table (view) again, after the countries array is updated (an element is deleted from it).
How do I do that?
add
countries = countries;
after this line
countries.splice(itemIdx,1);
since reactivity/rerendering/UI update only marked after assignment.
For svelte to pick up the change to your array of countries, you need to create a new reference of the array. For this you could use the Array.filter method.
<script>
let countries = [
{ code: "AF", name: "Afghanistan" },
{ code: "AL", name: "Albania" },
{ code: "IL", name: "Israel" }
];
function deleteCountry(code) {
countries = countries.filter(c => c.code !== code)
}
</script>
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>Code</th>
<th>Name</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
{#if countries.length}
{#each countries as c, index}
<tr>
<td>{index+1}</td>
<td>{c.code}</td>
<td>{c.name}</td>
<td class="text-right">
<button on:click="{() => deleteCountry(c.code)}" class="btn btn-sm btn-danger">Delete</button>
</td>
</tr>
{/each}
{:else}
<tr>
<td colspan="4">There are no countries</td>
</tr>
{/if}
</tbody>
</table>
Also you can directly use the country code as an argument for the deleteCountry method.

How to loop over js object and populate values in the table?

I have js object that looks like this:
{
"id": 9,
"user_name": "John Kim",
"age": 25,
"is_elig": true
}
I have table where data should be populated, looks like this:
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Eligible</th>
</tr>
<tr>
<td id="id"></td>
<td id="user_name"></td>
<td id="age"></td>
<td id="is_elig"></td>
</tr>
</table>
I use JQuery in my project and I was wondering if there is a way to loop over js object and check if the key exist in table td cell id. If does exist then populate the value in the cell.
You could iterate the object:
var obj = {
"id": 9,
"user_name": "John Kim",
"age": 25,
"is_elig": true
}
$.each(obj, function (key, value) {
$("#" + key).text(value);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Eligible</th>
</tr>
<tr>
<td id="id"></td>
<td id="user_name"></td>
<td id="age"></td>
<td id="is_elig"></td>
</tr>
</table>
Without jQuery, it would not be a lot more difficult:
var obj = {
"id": 9,
"user_name": "John Kim",
"age": 25,
"is_elig": true
}
Object.entries(obj).forEach(([key, value]) =>
document.getElementById(key).textContent = value
);
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Eligible</th>
</tr>
<tr>
<td id="id"></td>
<td id="user_name"></td>
<td id="age"></td>
<td id="is_elig"></td>
</tr>
</table>
Iterate through your object:
let obj = {
"id": 9,
"user_name": "John Kim",
"age": 25,
"is_elig": true
}
Object.keys(obj).forEach(i => $('td#'+ i).text(obj[i]) );
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Eligible</th>
</tr>
<tr>
<td id="id"></td>
<td id="user_name"></td>
<td id="age"></td>
<td id="is_elig"></td>
</tr>
</table>
I think when you say "loop over js object" you mean "loop over js array of objects". In that case you might do something like this:
<table>
<tr id="tr_users">
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Eligible</th>
</tr>
<div id="tr_users"></div>
</table>
In your js file:
var users = [];
var data = [ALL USERS IN ARRAY];
function setTable(data ) {
data .forEach(u => {
if(userIsNewInTable(u)) {
users.push(u);
}
});
users.forEach(u => {
appendInTable(u);
});
}
function userIsNewInTable(user) {
return !users.includes(user);
}
function appendInTable(value) {
let htmlToInsert = "";
htmlToInsert = `<tr>
<td>${id}</td>
<td>${user_name}</td>
<td>${age}</td>
<td>${is_elig}</td>
</tr>`;
$('#tr_users').append(htmlToInsert);
}
In this approach, we are declaring an empty array that will be fullfilled with the users. We have a function "setTable" that will receive the array of all the data (data). It will iterate over them and check if they already are in the users array to avoid duplicated.
Once we finished the iteration, we can insert the html with all the "td".
Please let me know if that's what you were looking for.
I wish it helped you.
Goodbye!

Categories

Resources