My component is as below:
import React, {PropTypes} from 'react';
export default class Viewdesc extends React.Component {
render() {
return (
<div className="col-md-12 slide-row">
<div className="col-md-12 overview-about-property">
<div className="expandabletext less">
<div className="col-md-12" dangerouslySetInnerHTML={{__html: this.props.record.ABOUT}}></div>
</div>
<div className="showmore"> Show More </div>
</div>
</div>
);
}
}
I want to call function say showmorefunct() passing clicked handler like this in jquery. How can I do this?
You can bind you function and pass params which you want, if you want to. You can do something like :
class Test extends React.Component {
handleClick(param, e){
console.log(e);
console.log(param);
}
render(){
return (
<div className="showmore" onClick={this.handleClick.bind(this, "Some param if you need it")}> Show More </div>
)
}
}
React.render(<Test />, document.getElementById('container'));
Here is fiddle.
UPDATE
http://jsfiddle.net/jwm6k66c/1517/
I don't quite really understand your question, but I imagine you want this-
import React, {PropTypes} from 'react';
export default class Viewdesc extends React.Component {
constructor(props) {
super(props)
this.showMoreFunct = this.showMoreFunct.bind(this)
}
showMoreFunct() {
alert('Show more clicked!')
}
render() {
return (
<div className="col-md-12 slide-row">
<div className="col-md-12 overview-about-property">
<div className="expandabletext less">
<div className="col-md-12" dangerouslySetInnerHTML={{__html: this.props.record.ABOUT}}></div>
</div>
<div className="showmore"> <span onClick={this.showMoreFunct}>Show More</span> </div>
</div>
</div>
);
}
}
You can replace span with a or button. You just need to specify the function you want to call to onClick prop. React will call it automatically when the user clicks on that span.
Related
Having this file:
Product.jsx:
class Product extends React.Component{
render(){
return (
<div className='item'>
<div className='image'>
<img src="images/products/image-aqua.png" />
</div>
<div className="middle aligned content">
<div className="description">
<a>Fort Knight</a>
<p>Authentic renaissance actors, delivered in just two weeks.</p>
</div>
<div className="extra">
<span>Submitted by:</span>
<img src="images/avatars/daniel.jpg" className="ui avatar image" />
</div>
</div>
</div>
)
}
}
export default Product;
and ProductList.jsx:
import Product from "./Product";
class ProductList extends React.Component{
render(){
return (
<div className='ui unstackable items'>
<Product />
</div>
)
}
}
ReactDOM.render(
<ProductList />,
document.getElementById('content')
);
The React Class <Product /> is not rendered (If I try to simply paste the Product class into ProductList.jsx, no problem then, but I want separate files for each class, how to achieve that?)
Use in Product.jsx the import React from "react";
demo in stackblitz
First import React at the top.
import React from "react";
Second you might be giving the wrong address at the top. Make sure it is right. You know the path well. Apart from these I don't see any problem with the code.
import Product from "./Product";
I have a parent component 'Menu' and a child component 'DishDetails'. The child component returns a Card on Button Click. It works for the first time when i click on the button. The component is not updated while i again click on button. The Component should update after clicking on the Button.
Parent Component
import React,{Component} from 'react';
import DishDetails from './DishDetails'
import { Card,CardImg,CardImgOverlay,CardTitle,CardBody,CardText} from 'reactstrap'
class Menu extends Component{
//The class base component must have a constructor with super statment
constructor(props){
super(props);
this.state ={
dishSelection:null
}
}
//Method when the user click on the image
onDish(dish){
this.setState({dishSelection:dish})
}
renderDish(dish){
if(dish!=null){
return(
<DishDetails dish = {dish}></DishDetails>
)
}
else{
return(
<div></div>
)
}
}
//The component should implement the render method
render(){
//Declare a variable for the defining the list
const media = this.props.dishes.map((dish)=>{
return(
<div className='col-12 col-md-5 m-2'>
<Card onClick={()=>this.onDish(dish)} key={dish.id}>
<CardImg src={dish.image} alt={dish.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
)
})
return(
<div className='container'>
<div className='row'>
{media}
</div>
<div className='row'>
<div className = 'col-12'>
{this.renderDish(this.state.dishSelection)}
</div>
</div>
</div>
)
}
}
export default Menu;
Child Component
import React , {Component} from 'react'
import {Card,CardImg,CardImgOverlay,CardTitle} from 'reactstrap'
class DishDetails extends Component{
constructor(props){
super(props)
this.state = {
dish : this.props.dish
}
}
render(){
//const dish = this.props.dish;
console.log(this.state.dish.name)
return(
<div>
<div className = 'col-12 col-md-5'>
<Card key={this.state.dish.id}>
<CardImg src={this.state.dish.image} alt={this.state.dish.name} />
<CardImgOverlay>
<CardTitle>{this.state.dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
<div>
</div>
</div>
)
}
}
export default DishDetails;
Constructor fires for the first time only. Don't make copy of props in state if you don't need to change the value inside child component. Change this.state.dish to this.props.dish in child component.
class DishDetails extends Component{
render(){
return(
<div>
<div className = 'col-12 col-md-5'>
<Card key={this.props.dish.id}>
<CardImg src={this.props.dish.image} alt={this.state.dish.name} />
<CardImgOverlay>
<CardTitle>{this.props.dish.name}</CardTitle>
</CardImgOverlay>
</Card>
</div>
<div>
</div>
</div>
)
}
}
export default DishDetails;
Or if you still want to update the state on any change in parent component then you should have a look at this link :-
https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops
I have made CARD's which display's username. When I click on the delete button i.e cross or cancel button it should remove the CARD's from the tasklist here tasklist is state variable. I am using .map() method to iterate over each task and display it. I want to delete the task card of a particular user when I click on the red cross button (see screenshot) currently only the window appears saying -> are you sure you want to delete it if I click yes it should delete it.
Code:
import React, {Component} from "react";
export default class Tasks extends Component{
constructor(props){
super(props);
this.state = {
taskList:[],
taskName:"",
type:"classification",
datasetName:"",
allDatasets:[],
users:[],
names:[]
}
}
triggerDelete(task){
if(window.confirm("Are you sure you want to delete this task?")){
}
}
render(){
return(
<div className="tasks-wrap">
<h1 onClick={()=>{
this.props.history.push("/taskdetails");
}}>Your Tasks</h1>
{
this.state.taskList.map((task,index)=>{
return(
<div key={index} className="item-card" onClick={()=>{
window.sessionStorage.setItem("task",JSON.stringify(task));
this.props.history.push("/taskdetails/");
}}>
<div className="name">{task.name}</div>
<div className="sub">
<div className="type">Dataset: {task.dateSetName}</div>
<div className="members">{task.userList.length + " participants"}</div>
</div>
<div className="del-wrap" onClick={(e)=>{
e.stopPropagation();
e.preventDefault();
this.triggerDelete(task);
}}>
<img src={require("../../images/cancel.svg")}/>
</div>
</div>
);
})
}
</div>
</div>
</div>
</div>
)
}
}
How should I modify my triggerDelete() method? So that the particular card gets deleted.
Pass index of the deleting task to the triggerDelete function and then just remove that index from this.state.taskList array.
<div className="del-wrap" onClick={(e)=>{
e.stopPropagation();
e.preventDefault();
this.triggerDelete(task, index);
}}>
<img src={require("../../images/cancel.svg")}/>
</div>
And in triggerDelete function
triggerDelete(task, index){
if(window.confirm("Are you sure you want to delete this task?")){
let taskList = [...this.state.taskList]
taskList.splice(index, 1);
this.setState({taskList: taskList})
}
}
you need to write the logic to delete the task, its easier to do it if you pass the index of the task to triggerDelete. window.confirm returns a boolean value indicating whether OK or Cancel was selected (true means OK).
import React, {Component} from "react";
export default class Tasks extends Component{
constructor(props){
super(props);
this.state = {
taskList:[],
taskName:"",
type:"classification",
datasetName:"",
allDatasets:[],
users:[],
names:[]
}
}
triggerDelete(index){
if(window.confirm("Are you sure you want to delete this task?")){
this.setState(prevState => ({
taskList: [...prevState.taskList.slice(0, index), ...prevState.taskList.slice(index + 1)]
}))
}
}
render(){
return(
<div className="tasks-wrap">
<h1 onClick={()=>{
this.props.history.push("/taskdetails");
}}>Your Tasks</h1>
{
this.state.taskList.map((task,index)=>{
return(
<div key={index} className="item-card" onClick={()=>{
window.sessionStorage.setItem("task",JSON.stringify(task));
this.props.history.push("/taskdetails/");
}}>
<div className="name">{task.name}</div>
<div className="sub">
<div className="type">Dataset: {task.dateSetName}</div>
<div className="members">{task.userList.length + " participants"}</div>
</div>
<div className="del-wrap" onClick={(e)=>{
e.stopPropagation();
e.preventDefault();
this.triggerDelete(index);
}}>
<img src={require("../../images/cancel.svg")}/>
</div>
</div>
);
})
}
</div>
</div>
</div>
</div>
)
}
}
I have a userlist which contains name and email id of each user. I want to display it using the .map() method on userlist state variable. I have created displayusers() function to display the users but I am getting failed to compile error.
Code:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state = {
userlist:[
{'name':'Rohan Singh',
'email':'rohan#gmail.com'
},
{'name':'Mohan Singh',
'email':'mohan#gmail.com'
},
{'name':'Rakesh Roy',
'email':'rakesh#gmail.com'
},
{'name':'Sunil Shah',
'email':'sunil#gmail.com'
}]
}
}
displayusers(){
return this.state.userlist.map( user => {
return(
<div className="item-card">
<div className="sub">
<div className="type">Username: {user.name}</div>
<div className="members">Email: {user.email}</div>
</div>
<div className="del-wrap">
<img src={require("../../images/cancel.svg")}/>
</div>
</div>
);
})
}
render() {
return(
<div className="users-wrap">
<h1>Users</h1>
<div className="task-content">
<div className="user-wrap">
<div className="users">
{this.displayusers()}
</div>
</div>
</div>
</div>
);
}
}
export default App;
I think you forgot about adding a key attribute to the element and there's missing </div> closing tag in your map function.
See the corrected code:
displayusers(){
return this.state.userlist.map( user => {
return(
<div className="item-card" key={user.name}>
<div className="sub">
<div className="type">Username: {user.name}</div>
<div className="members">Email: {user.email}</div>
</div>
<div className="del-wrap">
<img src={require("../../images/cancel.svg")}/>
</div>
</div>
);
});
}
You need to bind your displayusers function to this. You can do that in the constructor.
Update your code as following:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state = {
userlist:[
{'name':'Rohan Singh',
'email':'rohan#gmail.com'
},
{'name':'Mohan Singh',
'email':'mohan#gmail.com'
},
{'name':'Rakesh Roy',
'email':'rakesh#gmail.com'
},
{'name':'Sunil Shah',
'email':'sunil#gmail.com'
}]
};
this.displayusers = this.displayusers.bind(this); // you need to add this line
}
displayusers(){
return this.state.userlist.map((user, index) => {
return(
<div className="item-card" key={index}>
<div className="sub">
<div className="type">Username: {user.name}</div>
<div className="members">Email: {user.email}</div>
</div>
<div className="del-wrap">
<img src={require("../../images/cancel.svg")}/>
</div>
);
})
}
render() {
return(
<div className="users-wrap">
<h1>Users</h1>
<div className="task-content">
<div className="user-wrap">
<div className="users">
{this.displayusers()}
</div>
</div>
</div>
</div>
);
}
}
export default App;
I have a parent component, which is basically a Form.
export default class Parent extends Component{
submitInput(event){
...call Children
}
render(){
return(
<div>
<form className="form-horizontal" onSubmit= {this.submitInput.bind(this)}>
{this.props.children}
<button type="submit">Submit</button>
</div>
</form>
</div>);
}}
The children can be different types of inputs all with a common function called validate().
Here is one example of a child
export default class Child extends Component{
validate(){
..validate stuff
}
render(){
return(
<div className="form-group">
<textarea ref={this.props.name} />
</div>
);
}
}
On Submission of the parent Component I want validate all Child inputs using their validate() function.
How can I do that?
Thanks in advance
Clone the entire children with new ref prop using React.cloneElement. On submit use the refs to access the child's methods.
See the example below. If more elaboration needed, please comment.
Hope this helps!
class Form extends React.Component{
submitInput(){
this.childrenClone.forEach((el) => {
var r = el.ref //use the ref to access the child's methods
this.refs[r].validate()
})
}
render() {
this.childrenClone = React.Children.map(this.props.children,
(child) => React.cloneElement(child, {
ref: Math.random().toString(36).slice(-5) //add a random string as a ref
})
)
return <div>
<form className="form-horizontal" onSubmit={this.submitInput.bind(this)}>
{this.childrenClone}
<button type="submit">Submit</button>
</form>
</div>
}
}
class Child extends React.Component{
validate(){
console.log('validate textarea') //on validate log this
}
render() {
return <div className="form-group">
<textarea />
</div>
}
}
class ChildInput extends React.Component{
validate(){
console.log('validate Input') //on validate log this
}
render() {
return <div className="form-group">
<input type="text" />
</div>
}
}
class Parent extends React.Component{
render(){
return <Form>
<Child/>
<Child/>
<ChildInput/>
<ChildInput/>
</Form>
}
}
ReactDOM.render(<Parent/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>