I want id of image on click of delete button - reactjs

**i want id of the particular image at Onclick in reactjs. we have an array with all the data about images i.e. images[ ]. How to pass the id of that particular image to delete it to deleteimage function. any suggestion or advice will be welcomed **
class Image extends Component {
constructor() {
super();
this.state = { images: [] };
}
componentDidMount() {
let result = apiGateway.getImages();
if (result != null) {
result.then((value) => {
this.setState({ images: value.data.data });
});
}
}
deleteImage=()=>{
let result = apiGateway.removeImage(??);
}
renderImage(value,index){
let str = value.imagePath.split('/').pop();
let string = str.slice(0,-5);
return(
<div key={index}>
<p>Title: {value.title}</p>
<p>Description: {value.description}</p>
<button onClick={this.deleteImage}>DELETE</button>
<button>UPDATE</button>
<img className='image' src= {'http://localhost:3000/'+ string } width='100' height='100' alt='nature'/>
<br/><br/>
</div>
);
}
render() {
return(
<div>
<div>{
this.state.images.map((image,index)=>{
return this.renderImage(image,index);
})
}
</div>
</div>
);
}
}
export default Image;

Try send value to deleteImage(value) function:
<button onClick={this.deleteImage.bind(this, value)}>DELETE</button>
OR
<button onClick={(e) => this.deleteImage(value, e)}>DELETE</button>
Please view more here

Related

When I press the button I want to add many Employees, but it only leaves me one. React

Good morning, I have a question. When I press the + button, only one employee line is added and I would like it to be added as many times as I press
ReactJS component code:
class Home extends React.Component {
state = { showForm:false }
showForm = () => {
return(
<Employee />
)
}
render() {
return (
<div className='container-home'>
<div className='min-margin'>
<Employee />
{this.state.showForm ? this.showForm() : null}
<div className='container-append'>
<button onClick={() => this.setState({showForm: true})}>➕</button>
</div>
</div>
</div>
)
}
}
You just click to show and hide the input.
You need:
Add to state array: (inputs: ["Employee-0"])
state = {
showForm: false,
inputs: ["Employee-0"]
};
Add to functions
handleAddInput = e => {
e.preventDefault();
const inputState = this.state.inputs;
let inputs = inputState.concat([`Employee-${inputState.length}`]);
this.setState({
inputs
});
};
handleShowForm = e => {
e.preventDefault();
this.setState({
...this.state,
showForm: !this.state.showForm
})
}
Change the code in render
render() {
return (
<div className="App">
{this.state.showForm && <form>
{this.state.inputs.map((input, idx) => (
<Employee key={idx}/>
))}
</form>}
<button onClick={this.handleAddInput}>Add New Employee</button>
<button onClick={this.handleShowForm}>Show form</button>
</div>
);
}
Click on the buttons)
The difference options exist for doing it , but that's work you did just a flag for shown of a Component. So you are able to try followings this:
class Home extends React.Component {
state = {
employeesCount: 0,
employees: []
}
render() {
return (
<div className='container-home'>
<div className='min-margin'>
{employees.map((eNumber) => {
return <Employee key={eNumber}/>
}}
<div className='container-append'>
<button onClick={() => this.setState({
employeesCount: employeesCount + 1,
employees: [...this.state.employess , (employeesCount + 1)]
})}>➕</button>
</div>
</div>
</div>
)
}
}
Try this:
import React from "react";
const Employee = (props) => {
return(
<div>Hello I am employee number {props.number}</div>
)
}
class App extends React.Component {
constructor() {
super()
this.state = { employees: [] }
}
addEmployee() {
this.setState({
employees: [...this.state.employees, <Employee number={this.state.employees.length} />]
})
}
render() {
return (
<div>
<div className='container-append'>
<button onClick={() => this.addEmployee()}>➕</button>
</div>
{ this.state.employees.map(employee => employee) }
</div>
)
}
}
export default App;

Conditional rendering element from a list as a modal in React

I am very new to programming and working on an MVP project for a FS app where I have a small database of books which I render through a .map. Currently, I am rendering the cover of all the books in my database and when I click on the cover it shows the title, author and summary. The functionality is working but it is looking rubbish as when I click any book it pushes everything around and I would like for it to show as a modal box above my list of books. This is my code below, do you have any idea how to achieve that? Thanks so much :)
import Filter from "./components/filter"
import './App.css';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
books:[],
showBook: []
};
}
componentDidMount() {
this.getBookclub();
}
getBookclub = () => {
fetch(`/books`)
.then(response => response.json())
.then(response => {
this.setState({ books: response });
});
};
handleClick(e){
for (let i = 0 ; i < this.state.books.length ; i++) {
this.state.showBook[i] = false;
}
let bookShow = [...this.state.showBook];
bookShow[e.target.name-1] = true;
this.setState({
showBook: bookShow
});
}
renderLibrary() {
return this.state.books.map((books,id) => {
return(
<li key={id} className="book-list">
<span onClick ={() => this.getBookclub(books.id)}>
<div>
**<img onClick={(e) => this.handleClick(e)} name={books.id} src={books.cover} alt={books.title}/>
</div>
<div className={this.state.showBook[books.id-1] ? "bookDetails" : "bookhidden"}>
<br/>
<div className="cover-book-show">
<h5>{books.title}</h5>
</div>
<div className="author-book-show">
<h6>{books.author}</h6>
</div>
<div className="summary-book-show">
<p>{books.summary}</p>
</div>**
</div>
</span>
</li>
)
})}
filterBook(filteredList){
this.setState({
books: filteredList
})
}
render() {
return (
<div>
<h1>Books</h1>
<div>
<Filter filterBook={filteredList => this.filterBook(filteredList)}/>
</div>
<br/>
<ul>
**<div className="all-books">
{this.renderLibrary()}
</div>**
</ul>
</div>
);
}
}```

Updating the state of many children at once

I am trying to control the visibility of GalleryItem components by toggling skill components on/off that were used to create those projects. I would like to:
Show ALL if no skills have been toggled
If one or more skills are toggled, show only GalleryItems that use that skill
The selected skills are stored in state.portfolioTypes of Portfolio component - this works as expected.
I simply do not know how to call the updateDisplay method on each of my GalleryItem components from the click handler of my Skill components.
If someone can help me do that I am flying! Thanks.
I have tried pushing my GalleryItem components into an array that is in the parent state so that I can iterate over the array when toggling a Skill, but despite seeing the component objects when I log the array to the console, they are not rendered in the UI - instead are rendered numbers 13-24 (not sure why...)
resumeData.skills looks like:
skills: ["Branding", "Design", "UX", "Marketing", "Print", "Javascript", "HTML", "Grunt", "JQuery", "LessCSS", "Sketch", "Photoshop", "Illustrator", "Bootstrap"]
The item passed to GalleryItem class looks like:
{
imagePath: "images/portfolio/monster.png",
name: "Monster.com",
description: "Web design, UI Development and Art Direction",
modalImagePath: "images/portfolio/lrg/monster.png",
modalName: "Web design, UI Development and Art Direction",
modalDescription: "Working for one of the internet's biggest brands, I developed UI for internal incubator projects, components of the global web application and helped with the full UI redesign of the job seeker experience.",
modalCategories: ["Branding", "Design", "UX", "Photoshop", "Illustrator"],
url: "http://www.monster.com"
}
My Portfolio class containing Skill class and GalleryItem classes:
(I have removed some code not relevant to this question)
import React, { Component } from 'react';
export default class Portfolio extends Component {
constructor(props){
super(props);
this.state = {
portfolioTypes: [],
galleryItems: []
}
this.togglePortfolioItems = this.togglePortfolioItems.bind(this);
}
togglePortfolioItems(item){
//render only portfolio items with selected tags
console.log("togglePortfolioItems", item);
let portfolioTypes = this.state.portfolioTypes;
if(!item.isToggleOn){
portfolioTypes.push(item.type);
}else{
portfolioTypes.splice(portfolioTypes.indexOf(item.type), 1);
}
this.setState({portfolioTypes: portfolioTypes});
console.log(this.state.portfolioTypes, portfolioTypes);
}
render() {
let resumeData = this.props.resumeData;
let togglePortfolioItems = this.togglePortfolioItems;
let portfolioTypes = this.state.portfolioTypes;
let galleryItems = this.state.galleryItems;
return (
<React.Fragment>
<section id="portfolio">
<div className="row">
<div className="twelve columns collapsed">
<h1>Check Out Some of My Works.</h1>
<div className="skillToggles">
{resumeData.skills.map((item,index) => (
<Skill
skillName={item}
togglePortfolioItems={togglePortfolioItems}
galleryItems={galleryItems}
/>
))}
</div>
{/* portfolio-wrapper */}
<div id="portfolio-wrapper" className="bgrid-quarters s-bgrid-thirds cf">
{resumeData.portfolio.map((item,index) => (
galleryItems.push(<GalleryItem
item={item}
index={index}
portfolioTypes={portfolioTypes}
/>)
))}
</div> {/* portfolio-wrapper end */}
</div> {/* twelve columns end */}
</div> {/* row End */}
</section> {/* Portfolio Section End*/}
</React.Fragment>
);
this.setState({galleryItems: galleryItems});
}
}
class Skill extends Component {
constructor(props) {
super(props);
this.state = {
isToggleOn: false,
type: props.skillName.toLowerCase()
};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
this.props.togglePortfolioItems(this.state);
let galleryItems = this.props.galleryItems;
//loop through all galleryItems and set the display of each
galleryItems.map(galleryItem =>(
console.log(galleryItem);
//I would like to fire updateDisplay on galleryItem here
));
}
render() {
let skillName = this.props.skillName;
let skillNameId = skillName.toLowerCase();
return (
<React.Fragment>
<a href="" className={"skill "+(this.state.isToggleOn ? 'on' : 'off')} onClick={this.handleClick}>
{skillName}
</a> {/* Skill Section End*/}
</React.Fragment>
);
}
}
class GalleryItem extends Component{
constructor(props) {
super(props);
let portfolioTypes = this.props.portfolioTypes;
var displayed = true;
this.state = {
displayed: displayed
};
}
updateDisplay(){
let portfolioTypes = this.state.portfolioTypes;
let displayed = false;
if(portfolioTypes.length === 0){
displayed = true;
}else{
for(var x=0; x<portfolioTypes.length; x++){
let cat = portfolioTypes[x];
if(portfolioTypes.indexOf(cat) > -1){
displayed = true;
}
};
}
this.setState({displayed: displayed});
}
render() {
let item = this.props.item;
let index = this.props.index;
return (
<React.Fragment>
<div className={"columns portfolio-item "+(this.state.displayed ? "" : "hide ")+item.modalCategories.sort().join(" ").toLowerCase()}>
<div className="item-wrap">
<a href={"#modal-0"+index} title={item.name}>
<img alt src={item.imagePath} />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{item.name}</h5>
<p>{item.description}</p>
</div>
</div>
<div className="link-icon"><i className="icon-plus" /></div>
</a>
</div>
</div>
</React.Fragment>
);
}
}
When I toggle a skill, I would like the gallery to update to only display GalleryItems that used the selected skills.
Perhaps you can also suggest improvements to my approach, as there is probably a better/easier/more robust way to achieve this.
change updateDisplay function like this
updateDisplay(){
let portfolioTypes = this.props.portfolioTypes;
let displayed = false;
if(portfolioTypes.length === 0){
displayed = true;
}else{
for(var x=0; x<portfolioTypes.length; x++){
let cat = portfolioTypes[x];
if(portfolioTypes.indexOf(cat) > -1){
displayed = true;
}
};
}
return displayed;
}
Then Define a variable inside render
var displayed = this.updateDisplay()
use this variable instead of this.state.displayed
import React, { Component } from 'react';
export default class Portfolio extends Component {
constructor(props){
super(props);
this.state = {
portfolioTypes: []
}
this.togglePortfolioItems = this.togglePortfolioItems.bind(this);
}
togglePortfolioItems(item){
//render only portfolio items with selected tags
console.log("togglePortfolioItems", item);
let portfolioTypes = this.state.portfolioTypes;
if(!item.isToggleOn){
portfolioTypes.push(item.type);
}else{
portfolioTypes.splice(portfolioTypes.indexOf(item.type), 1);
}
this.setState({portfolioTypes: portfolioTypes});
console.log(this.state.portfolioTypes, portfolioTypes);
}
render() {
let resumeData = this.props.resumeData;
let togglePortfolioItems = this.togglePortfolioItems;
let portfolioTypes = this.state.portfolioTypes;
return (
<React.Fragment>
<section id="portfolio">
<div className="row">
<div className="twelve columns collapsed">
<h1>Check Out Some of My Works.</h1>
<div className="skillToggles">
{resumeData.skills.map((item,index) => (
<Skill
skillName={item}
key={index}
togglePortfolioItems={togglePortfolioItems}
/>
))}
</div>
{/* portfolio-wrapper */}
<div id="portfolio-wrapper" className="bgrid-quarters s-bgrid-thirds cf">
{resumeData.portfolio.map((item,index) => (
<GalleryItem
item={item}
index={index}
key={index}
portfolioTypes={portfolioTypes}
/>
))}
</div> {/* portfolio-wrapper end */}
</div> {/* twelve columns end */}
</div> {/* row End */}
</section> {/* Portfolio Section End*/}
</React.Fragment>
);
}
}
class Skill extends Component {
constructor(props) {
super(props);
this.state = {
isToggleOn: false,
type: props.skillName
};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
e.preventDefault();
this.setState(state => ({
isToggleOn: !state.isToggleOn
}));
this.props.togglePortfolioItems(this.state);
}
render() {
let skillName = this.props.skillName;
return (
<React.Fragment>
<a href="#" className={"skill "+(this.state.isToggleOn ? 'on' : 'off')} onClick={this.handleClick}>
{skillName}
</a> {/* Skill Section End*/}
</React.Fragment>
);
}
}
class GalleryItem extends Component{
constructor(props) {
super(props);
let portfolioTypes = this.props.portfolioTypes;
}
updateDisplay(){
console.log("updateDisplay");
let portfolioTypes = this.props.portfolioTypes;
let item = this.props.item;
let displayed = false;
if(portfolioTypes.length === 0){
displayed = true;
}else{
for(var x=0; x<portfolioTypes.length; x++){
let cat = portfolioTypes[x];
if(item.modalCategories.indexOf(cat) > -1){
displayed = true;
}
};
}
return displayed;
}
render() {
let item = this.props.item;
let index = this.props.index;
var displayed = this.updateDisplay();
return (
<React.Fragment>
<div className={"columns portfolio-item "+(displayed ? "" : "hide ")+item.modalCategories.sort().join(" ")}>
<div className="item-wrap">
<a href={"#modal-0"+index} title={item.name}>
<img alt="Gallery Image" src={item.imagePath} />
<div className="overlay">
<div className="portfolio-item-meta">
<h5>{item.name}</h5>
<p>{item.description}</p>
</div>
</div>
<div className="link-icon"><i className="icon-plus" /></div>
</a>
</div>
</div>
</React.Fragment>
);
}
}

React: change order list when button clicked

I am making my first app with Javascript and React and started with a page which views a shopping list. It gets the items from an api call.
If the user clicks on the button 'done' (or should I use an checkbox?) This product should go to the bottom of the list (and be grayed out with css but thats not the problem).
The problem is, I have no clue how to do this. Can anyone help me out a bit?
This is my code:
import React from 'react';
//import image from '../images/header.png';
//import Collapsible from './Collapsible';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
orders: []
}
}
componentWillMount() {
localStorage.getItem('orders') && this.setState({
orders: JSON.parse(localStorage.getItem('orders')),
isLoading: false
})
}
componentDidMount() {
if (!localStorage.getItem('orders')){
this.fetchData();
} else {
console.log('Using data from localstorage');
}
}
fetchData() {
fetch('http://localhost:54408/api/orders/all/15-03-2018')
.then(response => response.json())
.then(parsedJSON => parsedJSON.map(product => (
{
productname: `${product.ProductName}`,
image: `${product.Image}`,
quantity: `${product.Quantity}`,
isconfirmed: `${product.IsConfirmed}`,
orderid: `${product.OrderId}`
}
)))
.then(orders => this.setState({
orders,
isLoading: false
}))
.catch(error => console.log('parsing failed', error))
}
componentWillUpdate(nextProps, nextState) {
localStorage.setItem('orders', JSON.stringify(nextState.orders));
localStorage.setItem('ordersDate', Date.now());
}
render() {
const {isLoading, orders} = this.state;
return (
<div>
<header>
<img src="/images/header.jpg"/>
<h1>Boodschappenlijstje <button className="btn btn-sm btn-danger">Reload</button></h1>
</header>
<div className={`content ${isLoading ? 'is-loading' : ''}`}>
<div className="panel">
{
!isLoading && orders.length > 0 ? orders.map(order => {
const {productname, image, quantity, orderid} = order;
return<div className="product" key={orderid}>
<div className="plaatjediv">
<img className="plaatje" src={image} />
</div>
<div className="productInfo">
<p>{productname}</p>
<p>Aantal: {quantity}</p>
<p>ID: {orderid}</p>
</div>
<div className="bdone">
<button className="btn btn-sm btn-default btndone">Done</button>
</div>
</div>
}) : null
}
</div>
<div className="loader">
<div className="icon"></div>
</div>
</div>
</div>
);
}
}
export default App;
You can achieve by using this :
this.handleDoneAction = event = > {
let itemIndex = event.target.getAttribute("data-itemIndex");
let prevOrders = [...this.state.orders];
var itemToMoveAtLast = prevOrders.splice(itemIndex, 1);
var updatedOrderList = prevOrders.concat(itemToMoveAtLast);
this.setState({order: updatedOrderList})
}
I have attach an event handler on the button handleDoneAction.
<button className="btn btn-sm btn-default btndone" data-itemIndex={index} onClick={this.handleDoneAction}>Done</button>
the attribute data-itemIndex is the index of the object in orders array.
And your map function will be like this:
orders.map((order, index) => {
//content
})
ANd for the different style effects on the done products, I will suggest you to use different array for all done products.

react change the class of list item on click

I have a react element like this:
import React, { PropTypes, Component } from 'react'
class AlbumList extends Component {
constructor(props) {
super(props);
this.state = {'active': false, 'class': 'album'};
}
handleClick() {
if(this.state.active){
this.setState({'active': false,'class': 'album'})
}else{
this.setState({'active': true,'class': 'active'})
}
}
render() {
var album_list
const {user} = this.props
if(user.data){
list = user.data.filter(album => album.photos).map((album => {
return <div className={"col-sm-3"} key={album.id}>
<div className={this.state.class} key={album.id} onClick={this.handleClick.bind(this)}>
<div className={"panel-heading"}>{ album.name }</div>
<div className={"panel-body"}>
<img className={"img-responsive"} src={album.photo.source} />
</div>
</div>
</div>
}))
}
return (
<div className={"container"}>
<div className="row">
{list}
</div>
</div>
)
}
}
export default AlbumList
Here map gives the list of filter data as I wanted. Here what I am doing changes the class of all the list element if I click on one.
I am getting the class name from this.state.class
How can I change the class of only element that i have clicked..
Thanks in advance ...
I have considered it once.So you have so many divs and you want to know which is clicked.My way to solve this problem is to give a param to the function handleClick and you can get the dom of the div while you click the div.Like this:
array.map(function(album,index){
return <div onClick={this.handleClick}/>
})
handleClick(e){
console.log(e.target);
e.target.className = 'active';
...
}
Then you have a param for this function.While you can use the e.target to get the dom of your div which is clicked.
There are some mistake into your code about the state.class.
class AlbumList extends Component {
constructor(props) {
super(props);
this.state = {'active': false, 'class': 'album'};
}
handleClick(e) {
if(e.target.class === 'active'){
e.target.className = 'album'
}else{
e.target.className = 'active'
}
}
render() {
var album_list
const {user} = this.props
if(user.data){
list = user.data.filter(album => album.photos).map((album => {
return (
<div className={"col-sm-3"} key={album.id}>
<div className='active' key={album.id} onClick={this.handleClick.bind(this)}>
<div className={"panel-heading"}>{ album.name }</div>
<div className={"panel-body"}>
<img className={"img-responsive"} src={album.photo.source} />
</div>
</div>
</div>
)
}))
}
return (
<div className={"container"}>
<div className="row">
{list}
</div>
</div>
)
}
}
You can try this and tell me anything wrong.

Resources