How to populate a HTML div from array object? - javascript

I was YouTube video on ReactJS where it populate a div container from a array object using .map() . Is there any way to do it using vanilla js or jquery in simple HTML ?
ReactJS code is provided below -
ProductCategories.JSX
import { categories } from "../dataList";
import CategoryItem from "./CategoryItem";
<div className="* * *">
{categories.map((item) => (
<CategoryItem item={item} key={item.id} />
))}
</div>
CategoryItem.JSX
import styled from "styled-components";
<Container>
<Image src={item.Image} />
<Info>
<Title>{item.Title}</Title>
<Button>SHOP NOW</Button>
</Info>
</Container>
dataList.js
export const categories = [
{
id: 1,
Image: "https://i.ibb.co/CnkbTqm/download-ixid-Mnwx.jpg",
Title: "Lorem",
},
{
id: 2,
Image: "https://i.ibb.co/CnkbTqm/download-ixid.jpg",
Title: "Ipsum",
},
{
id: 3,
Image: "https://i.ibb.co/CnkbTqm/download.png",
Title: "lorem",
},
];

One way, using reduce():
Loop through the categories using reduce(), for each object return a string (concatenating the previous value) that contains:
A <h1> created with cat.Title
A <img> created with cat.Image
Set the string as innerHTML of your element
Using <body> as demo
const categories = [{id: 1, Image: "https://i.ibb.co/CnkbTqm/download-ixid-Mnwx.jpg", Title: "Lorem", }, {id: 2, Image: "https://i.ibb.co/CnkbTqm/download-ixid.jpg", Title: "Ipsum", }, {id: 3, Image: "https://i.ibb.co/CnkbTqm/download.png", Title: "lorem", }, ];
document.body.innerHTML = categories.reduce((prev, cat) => prev + `<h2>${cat.Title}</h2> <img src='${cat.Image}' />`, '');
We can get the same idea/behaviour/output using map() and join() instead off reduce() like so:
const categories = [{id: 1, Image: "https://i.ibb.co/CnkbTqm/download-ixid-Mnwx.jpg", Title: "Lorem", }, {id: 2, Image: "https://i.ibb.co/CnkbTqm/download-ixid.jpg", Title: "Ipsum", }, {id: 3, Image: "https://i.ibb.co/CnkbTqm/download.png", Title: "lorem", }, ];
document.body.innerHTML = categories.map(cat => `<h2>${cat.Title}</h2> <img src='${cat.Image}' />`).join('');

you can use createElement() api https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
here are some ideas in vanilla
var div = document.createElement('div');
var link = document.createElement('a');
var article = document.createElement('article');
and here in Jquery
var elem = $('<div></div>')
you can create element and append to the them container.

Related

How can i grab one of my elements in the array and style it?

Hi devs im learning React and i want to know if there's a method to grab an element from my array
and style it with css.
const card = [
{
id: 1,
title: "DEEP EARTH",
Background: "images/earth.jpg",
},
{
id: 2,
title: "NIGHT ARCADE",
Background: "images/arcade.jpg",
},
{
id: 3,
title: "SOCCER TEAM VR",
Background: "images/soccer.jpg",
}
]
As early was said you can use map and inline styles
return (<div>
{card.map((item) => (
<div key={item.id}>{item.title}
styles={{background:url(item.src)}}
>
</div>
))}
</div>);
You will need to render this using map, and then you could apply any css you want with it.
this might help:
https://reactjs.org/docs/lists-and-keys.html
you could add a property to the ones you want styled:
const card = [
{
id: 1,
title: "DEEP EARTH",
Background: "images/earth.jpg",
style: {"color": "red"}
},
{
id: 2,
title: "NIGHT ARCADE",
Background: "images/arcade.jpg",
},
];
and then use map:
{
card.map((cardItem, index) => {
return <div>
<span style={cardItem.style}>{cardItem.title}</span>
</div>
})
}
and in the same manner you could have that property point to a css class you have defined and use className.

Is it possible to pass variable to antD Statistics component in React?

I'm trying to render data from a variable / function into an antD Statistic Component. It appears it can only take a raw string or number, but I need to pass data from props into it.
Is there a way around this? See code below - I would like to pass scenarios[0].investment into "Statistic title="Investment" value={scenarios[0].investment}" but it doesn't allow it. Current code below works AS-IS but breaks when I replace it with scenarios[0].investment
class RenderSummary extends Component {
state = {
clicked: false,
hovered: false,
};
hide = () => {
this.setState({
clicked: false,
hovered: false,
});
};
handleHoverChange = visible => {
this.setState({
hovered: visible,
clicked: false,
});
};
handleClickChange = visible => {
this.setState({
clicked: visible,
hovered: false,
});
};
render() {
const scenarios = this.props.scenarios;
const data = [
{
title: 'Title 1', content: <Statistic title="Investment" value={0}/>,
},
{
title: 'Title 2', content: <Statistic title="T Savings" value={0}/>,
},
{
title: 'Title 2', content: <Statistic title="E Savings" value={0}/>,
},
];
const hoverContent = <div>This is hover content.</div>;
const clickContent = <div>This is click content.</div>;
const onClick = () => console.log("Works!");
return(
<div className="container">
<div className="site-card-wrapper">
<Row gutter={16}>
<Col span={12}>
<Card title="User Scenario 1" bordered={true}>
<List
grid={{ gutter: 16, column: 3 }}
dataSource={data}
renderItem={item => (
<List.Item>
{item.content}
</List.Item>
)}
/>
</Card>
</Col>
</Row>
</div>
</div>
);
}
}
scenarios in props as follows
"scenarios : [0: {id: 0, investment: 0, tSavings: 0, eSavings: 0 …},1: {id: 0, investment: 1, tSavings: 1, eSavings: 1 …}]"
I think the way you have structured your scenarios array or the way you are passing it is incorrect.
An example of how you could pass scenarios to RenderSummary:
const App = () => {
const scenarios = [
{investment: 1}, // Add your other properties
{investment: 2},
{investment: 3},
]
return <RenderSummary scenarios={scenarios}/>
}
If you pass scenarios like above, you can pass it in the way you wanted to:
const data = [
{
title: "Title 1",
content: <Statistic title="Investment" value={scenarios[0].investment} />,
},
{
title: "Title 2",
content: <Statistic title="T Savings" value={scenarios[1].investment} />,
},
{
title: "Title 2",
content: <Statistic title="E Savings" value={scenarios[2].investment} />,
},
];

mapping through array of objects and accessing object values

I am trying to pick a value from array of object and the values can only be from first object.
Firstly i have a array of objects like this:
items [
[
{id: 1, title: "title1", imgUrl: "https://someimage1"},
{id: 2, title: "title2", imgUrl: "https://someimage2"}
],
[
{id: 1, title: "title1", imgUrl: "https://someimage1"},
{id: 2, title: "title2", imgUrl: "https://someimage2"}
],
[
{id: 1, title: "title1", imgUrl: "https://someimage1"},
{id: 2, title: "title2", imgUrl: "https://someimage2"}
]
]
I am planning to display the title and img url on the page. I am using react and this is what i have tried so far:
items.map(item => {
//here i enter each array of the big array individually
//here i will enter first object of the give array
console.log('ITEM:', item[0])
})
in console.log i get this:
ITEM: {id: 1, title: "title1", imgUrl: "https://someimage1"}
ITEM: {id: 1, title: "title1", imgUrl: "https://someimage1"}
ITEM: {id: 1, title: "title1", imgUrl: "https://someimage1"}
but I need to get each title and imgUrl so in my .map() I do this:
items.map(item => {
//here i enter each array of the big array individually
//here i will enter first object of the give array
console.log('ITEM:', item[0].title)
})
but I get this error:
TypeError: Cannot read property 'title' of undefined
I don't understand why I thought I would be able to use dot notation to access whatever key in the object you would like:
for more context:
<div>
{
items.map((item) => {
return <ul>
<li>
<div>
<p>{item[0].title}</p>
<img src={item[0].url}/>
</div>
</li>
</ul>
})
}
</div>
MY SOLUTION TO THE ABOVE PROBLEM
SO i have spend some time messing around with this issue and this works for me:
items.map((item) => {
return item.map ((x, index) => {
if (index === 0) {
return <ul>
<li>
<div>
<p>{ x.title }</p>
<img src={x.url}/>
</div>
</li>
</ul>
}
})
})
Still not sure why my initial idea item[0].title not work without having nested map() function
Try using quotes around the keys:
items [
[
{"id": 1, "title": "title1", "imgUrl": "https://someimage1"},
{"id": 2, "title": "title2", "imgUrl": "https://someimage2"}
]
]
[Update Based on OP updating Post:
Since map builds a new array, using it when you aren't using the returned array is an anti-pattern; use forEach or for-of instead.
Signs you shouldn't be using map:
A) You're not using the array it
returns, and/or
B) You're not returning a value from the callback.
Further reading on .map() via Mozilla
Furthermore nesting 2 loops in such a way will force twice as many iterations as it will still run length times.
If you need to access a sub element and know its index or key then use that value by:
array[index] or object.key and use a single map() (example in full snippet)
If you do actually need to loop over every element (due to some condition not expressed in your question) instead use:
.find() (single elements)
or .filter(elm => elm === 'someValue') (multiple elements)
or .reduce() (multiple elements) with mutating elements as you go
or even .forEach() (multi elements) with performing additional functions outside of array building (you will need to push to something like let loopArray = [])
Continue Original Answer]
Move the ul tag outside the map statement and change url to imgUrl.
Keep in mind if items is generated via async then you will also need to validate items before using map, something like:
{(items && items.length) && items.map(item=>{
/*code*/
)}
Working Snippet (without async check):
const SomeComponent = () => {
const items = [
[
{id: 1, title: "title1.1", imgUrl: "https://p7.hiclipart.com/preview/917/362/567/halloween-trick-or-treating-double-ninth-festival-illustration-halloween-design-elements.jpg"},
{id: 2, title: "title2", imgUrl: "https://someimage2"}
],
[
{id: 1, title: "title1.2", imgUrl: "https://image.shutterstock.com/image-vector/silhouette-cat-dog-on-white-600w-671156590.jpg"},
{id: 2, title: "title2", imgUrl: "https://someimage2"}
],
[
{id: 1, title: "title1.3", imgUrl: "https://jngnposwzs-flywheel.netdna-ssl.com/wp-content/uploads/2019/05/Transparent-OrangeWhiteCat-768x1030.png"},
{id: 2, title: "title2", imgUrl: "https://someimage2"}
]
];
return (
<div>
<ul>
{items.map((item,index) => {
return(
<li key={String(index)}>
<div>
<p>{item[0].title}</p>
<img style={{width:'10%'}} src={item.imgUrl} alt={item.title}/>
</div>
</li>
)
})}
</ul>
</div>
)
}
ReactDOM.render(
<SomeComponent />,
document.getElementById("react")
);
<div id='react'></div>
<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>

Checkbox value wrong behavior on buefy

I generate a list of checkboxes from an array, and when I select some of the box, the v-model value (a generated array declared when Vue instance is created) doesn't add the new box value to the array but replace empty the array and place the value in it.
With an example : I got 3 values "Cat", "Dog" and "Bird". When I check "Cat", the array looks like that ["Cat"] and when I check "Dog" with "Cat", the array looks like that ["Dog"].
When I use a variable (array) defined in the data it works, but when I use my array in the form variable it doesn't work.
<div id="root">
<b-checkbox
v-for="(field, key) in query.fields"
v-model="form[query.id+'-'+query.priority]"
:native-value="field.id">
{{ field.name }}
</b-checkbox>
</div>
<script>
const vue = new Vue({
el: '#root',
data: {
query: {id: 1, priority: 1, fields: [{id: 1, name: 'cat'}, {id: 2, name: 'dog'}, {id: 3, name: 'bird'}]),
form: {},
},
created: function () {
this.form[this.query.id+'-'+this.query.priority] = [];
}
});
</script>
To solve the behaviour of my object, I transformed it into an array using the id of the query as the id of the form. I fetch the priority of the query elsewhere.
It solves my problem but not the problem of using a string as an index for this kind of code.
<div id="root">
<b-checkbox
v-for="(field, key) in query.fields"
v-model="form[query.id]"
:native-value="field.id">
{{ field.name }}
</b-checkbox>
</div>
<script>
const vue = new Vue({
el: '#root',
data: {
query: {id: 1, priority: 1, fields: [{id: 1, name: 'cat'}, {id: 2, name: 'dog'}, {id: 3, name: 'bird'}]),
form: [],
},
created: function () {
this.form[this.query.id] = [];
}
});
</script>

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