How to iterate images on React? - reactjs

Well, the question is very self-explanatory. I have this code here (inside a render, of course):
const images = [('http://placehold.it/100x100/76BD22'), ('http://placehold.it/100x100/76BD23')];
// ProductPage Views
const ProductPageView =
<section className="page-section ps-product-intro">
<div className="container">
<div className="product-intro">
<div className="product-intro__images">
<div className="product-gallery">
<ul className="product-gallery-thumbs__list">
{images.map(function(image, imageIndex){
return <li key={ imageIndex }>{image}</li>;
})}
</ul>
</div>
</div>
</div>
</div>
</section>
The thing is I don't know how to iterate those images on the array. What's wrong with my code?

Your array is an array of image URLs, not image tags. So your code is close but you need to put the image inside of an image tag inside of your list item tag.
const images = [('http://placehold.it/100x100/76BD22'), ('http://placehold.it/100x100/76BD23')];
// ProductPage Views
const ProductPageView =
<section className="page-section ps-product-intro">
<div className="container">
<div className="product-intro">
<div className="product-intro__images">
<div className="product-gallery">
<ul className="product-gallery-thumbs__list">
{images.map(function(imageSrc) {
return (
<li key={ imgSrc }>
<img src={ imgSrc } />
</li>
);
})}
</ul>
</div>
</div>
</div>
</div>
</section>
I would also recommend against using an array index as a key in general. The imgSrc is unique so it would make a good key here.
Also, make sure to include an alt attribute on the img for screen readers. You might want to make your array like this:
const images = [
{ src: 'http://placehold.it/100x100/76BD22', alt: 'Your description here 1' },
{ src: 'http://placehold.it/100x100/76BD23', alt: 'Your description here 2' }
];
// ...
{images.map(function(imageProps) {
return (
<li key={ imageProps.src }>
<img src={ imageProps.src } alt={ imageProps.alt } />
</li>
);
})}

I assume you want to display them as images, right? You should use img tag then.
<ul className="product-gallery-thumbs__list">
{images.map(function(image, imageIndex){
return <img key={ imageIndex } src={ image } />
})}
</ul>

Related

How to return a tree of react tags from a Map() object in React?

I want to return a return a structure like :
<div>
<div label=Category 1>
<ul>
<li>item1</li>
<li>item2</li>
</ul>
<br/>
</div>
<div label=Category 2>
<ul>
<li>item3</li>
<li>item4</li>
</ul>
<br/>
</div>
</div>
In order to achieve this, I created a Map() object an I want to iterate through categories and items. Desperately tried all sorts of ideas with no luck. I am not sure if is very simple or impossible in react. I am imagining to run stg. like this and 1) yet it does not return any value 2) splitting the ul tag is not allowed, apparently.
for (let [key, values] of lists) {
<div label={key}><ul>;
values.map(item => <li key={item.id}>{item.name}</li>);
</ul>
</div>
}
This is a working version of #Expressd3v's code (possibly with a couple of edits). I tried to add this to #Expressd3v answer but the edit's not been approved so maybe that wasn't the right way to go about it. Please don't upvote this as it's basically #Expressd3v answer.
Edited to use Map().
const Lists = ({ lists }) =>
<React.Fragment>
{
[...lists].map(([key, values]) => (
<div label={key} key={key}>
<ul>
{ values.map(item => <li key={item.id}>{item.name}</li>) }
</ul>
</div>
))
}
</React.Fragment>;
const App = () => {
let lists = new Map();
lists.set('Category 1', [
{ id: 1, name: 'item1' },
{ id: 2, name: 'item2' },
]);
lists.set('Category 2', [
{ id: 3, name: 'item3' },
{ id: 4, name: 'item4' },
]);
return <Lists lists={lists} />;
};
ReactDOM.render(<App />, document.getElementById('root'));
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<div id="root"></div>
Missing
For loop is not returning any value.
So you need to include a return.
for example:
for (let [key, values] of lists) {
return(
<div label={key}>
<ul>
{values.map(item => <li key={item.id}>{item.name}</li>);}
</ul>
</div>
)
}
My suggestion
Object.entries(lists).map(([key,values])=>(
<div label={key} key={key}>
<ul>
{values.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
</div>
)
))

Datapicker React - Having a hard time displaying the date

I am trying to render several inputs (name, location, # of plants and 2 dates).
The 2 dates dont want to get displayed for some reasons they stay in an array format... I tried trooble shooting in several ways but nothing does :(
Any idea?
Here is the App part
let InitialOwners = [
{ nameOwner: 'Julie S', locationOwner: "Eixample", plantsOwner: "2" , startDateOwner: [{}] , endDateOwner : [] }
];
function App() {
const [owners, setOwners] = useState(InitialOwners);
// to get the data from PO form
function handleOwnerData(ownerData) {
let newOwners = [...owners, ownerData];
setOwners(newOwners)
console.log(`Owner Data: ${ownerData.locationOwner} ${ownerData.nameOwner} ${ownerData.plantsOwner} ${ownerData.startDateOwner} ${ownerData.endDateOwner}`)
}
Here is the list part where the data should be displayed
import React from "react";
function DashboardUsers(props){
return (
<div className ="Dashboard">
<h2> Welcome to the Dashboard</h2>
<h4> Here are the current owners </h4>
<ul>
{
props.owners.map((owners,i) => (
<div key={i}>
<li> Name: {owners.nameOwner}</li>
<li> Location: {owners.locationOwner} </li>
<li> # of plants: {owners.plantsOwner} </li>
<li> Start Date: [owners.startDateOwner] </li>
<li> End Date:[owners.endDateOwner] </li>
</div>
))
}
</ul>
</div>
)
}
export default DashboardUsers;
And here is how it looks like on the browser :D
browser image
When you are mapping over an array with objects each entry in the map, in your case 'owners', represents the current object. In that case owners.startDateOwner is an array of objects inside an array of objects. If you want to iterate over it you need to nest another map:
{
props.owners.map((owners,i) => (
<div key={i}>
<li> Name: {owners.nameOwner}</li>
<li> Location: {owners.locationOwner} </li>
<li> # of plants: {owners.plantsOwner} </li>
<li> Start Date: {owners.startDateOwner.map((ownerStartDate) => <span>{ownerStartDate}</span>)} </li>
<li> End Date:[owners.endDateOwner] </li>
</div>
))
}
this will iterate over the dates and print them in a <span>

Angular Multi-item carousel

Ive been trying to make the angular carousel work, but iam currently stuck.
I am a newbie in angular, thus can i not get the ng-repeat too work correct.
what ive done:
<div id="slides_control">
<div>
<carousel interval="3000">
<slide ng-repeat="book in bookslider" active="book.active">
<div class="col-md-3"><img ng-src="{{book.img}}"></div>
<div class="col-md-3"><img ng-src="{{book[$index +1].img}}"></div>
<div class="col-md-3"><img ng-src="{{book[$index +2].img}}"></div>
<div class="col-md-3"><img ng-src="{{book[$index +3].img}}"></div>
<div class="carousel-caption">
<h4>Slide {{$index+1}}</h4>
</div>
</slide>
</carousel>
</div>
$scope.bookslider = [
{
img: "images/headerslider/5.jpg"
},
{
img: "images/headerslider/4.jpg"
},
{
img: "images/headerslider/2.jpg"
},
{
img: "images/headerslider/3.jpg"
}
];
This display only the first image because it cannot "render" - book[$index +1].img how would one go about getting the next index item for this situation?
Working plunk: http://plnkr.co/edit/VcD8tKOtfQGuOgt4tO08
I gone through the plunker you provided and I under stand your requirement. I think the mistake that you made is where you loop the bookslider object. You need to loop through bookslider object instead of that you looped through the book object which is actually an individual object of the bookslider array.
You just change the carousel object like this to fix the issue.
<carousel interval="3000">
<slide ng-repeat="book in bookslider track by $index" active="book.active">
<div class="col-md-3"><img ng-src="{{bookslider[($index) %4 ].img}}" style="width=100px"></div>
<div class="col-md-3"><img ng-src="{{bookslider[($index+1) % 4].img}}"></div>
<div class="col-md-3"><img ng-src="{{bookslider[($index+2) % 4].img}}"></div>
<div class="col-md-3"><img ng-src="{{bookslider[($index+3) % 4].img}}"></div>
<div class="carousel-caption">
<h4>Slide {{$index+1}}</h4>
</div>
</slide>
</carousel>
I have attached the working plunker here.

Filter object array with pipe Angular 2

I have a
class:
export class Todo {
public id: number;
public name: string;
public isCompleted: boolean;
public dateCreated: Date;
public userName: string;
}
A service:
getTodos(): Observable < Todo[] > {
return this.http.get(this.todosUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body || {};
}
In my component:
getTodos(){
this.todoService.getTodos()
.subscribe(
todos => this.todos = todos,
error => this.errorMessage = <any>error
);
}
And html file:
<div class="ui large selection animated divided list">
<a *ngFor="let todo of (todos | todoFilter:false)" class="item">
<div class="right floated content">
<div class="ui vertical animated negative button" tabindex="0">
<div class="hidden content">Delete</div>
<div class="visible content">
<i class="fa fa-trash" aria-hidden="true"></i>
</div>
</div>
</div>
<i class="minus square outline icon"></i>
<div class="content">
<div class="header">{{todo.name}}</div>
<div class="description">{{todo.dateCreated | date:"MMM-dd-yyyy"}}</div>
</div>
</a>
</div>
The problem is, when I try to use this pipe to filter the completed todos, I keep getting an error that say Cannot read property filter of undefined.
Did I do something wrong or are there any ways to filter it without using an pipe?
My pipe:
transform(allTodos: Todo[], args?: boolean){
if (allTodos === null) {
return null;
}
return allTodos.filter(todo => todo.isCompleted);
}
Thank you.
Try to replace the if (allTodos === null) to just if (!allTodos)
I think the problem is that you're getting to the .filter even while your this.todos is still empty since you're only checking that it isn't null.

How do I set the index on ng-repeated item for a ng-click?

I have an gallery image with thumbnails. When I click on a thumbnail, I want the main image to show the thumbnail index with it's full image. How do I add ng-click to get the current index?
<div ng-controller="GalleryController as gallery">
<img ng-src="{{product.images[gallery.current]}}" />
<div>
<img ng-src="{{image.thumb}}" ng-repeat="image in product.images" ng-click="gallery.setCurrent(image[i])" />
</div>
</div>
app.controller('GalleryController', function () {
this.current = 0;
this.setCurrent = function (val) {
this.current = val;
}
});
var gems = [
{
images: [
{
full: 'img/diamond.jpg',
thumb: 'img/diamond.jpg'
},
{
full: 'img/diamond2.jpg',
thumb: 'img/diamond2.jpg'
}
]},
];
Just pass the image object itself or use $index (ng-repeat puts this property on its scope) which will have the index of the currently iterated item.
Passing current image item:-
<img ... ng-repeat="image in product.images" ng-click="gallery.setCurrent(image)" />
or passing index of that item:-
<img ... ng-repeat="image in product.images" ng-click="gallery.setCurrent($index)" />

Resources