I'm trying to change display of div.Filters on click of plus or minus button. The button changes on click, if it's a + changes to -, and vice versa.
Here's the code:
export class NavLeftMobile extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
isToggle: true
};
}
handleClick(e) {
this.setState({
isToggle: !this.state.isToggle
});
}
render() {
let button;
if (this.state.isToggle) {
button = (
<button className="Menos" onClick={() => this.handleClick()}>
-
</button>
);
} else {
button = (
<button className="Menos" onClick={() => this.handleClick()}>
+
</button>
);
}
return (
<div>
<div className="NavLeftMobile">
<h1>categories</h1>
<h3>Manufacturer{button}</h3>
<div
className="Filters"
style={{ display: this.state.isToggle ? "block" : "none" }}
>
<p>Lusograph (10)</p>
</div>
<h3>Color{button}</h3>
<div
className="Filters"
style={{ display: this.state.isToggle ? "block" : "none" }}
>
<p>Black (10)</p>
</div>
</div>
</div>
);
}
}
So, when clicking on one of the buttons, handleClick function is called and the display from div.Filters changes, if it's block to none and vice versa.
Basically, I want to toggle each section independent from each other.
If you want each section to be Collapsible and indepent, then the state should not live on your wrapper component, instead you can create another class component that keeps track of it.
class Collapsible extends React.Component {
constructor(props) {
super(props);
this.state = {
collapsed: true
};
}
onToggle = () => {
const { collapsed } = this.state;
this.setState(() => ({
collapsed : !collapsed
}))
}
render () {
const { title, children } = this.props;
const { collapsed } = this.state;
return (
<div>
<h3>
{title}
<a onClick={this.onToggle}>
{collapsed ? '+' : '-'}
</a>
</h3>
<div style={{
display : collapsed ? "block" : "none"
}}>
{children}
</div>
</div>
);
}
}
class NavLeftMobile extends React.Component {
render() {
return (
<div>
<div className="NavLeftMobile">
<h1>categories</h1>
<Collapsible title="Manufacturer">
Lusograph (10)
</Collapsible>
<Collapsible title="Color">
Black (10)
</Collapsible>
</div>
</div>
);
}
}
ReactDOM.render(
<NavLeftMobile/>,
document.querySelector('#app')
);
Related
I am new in react Js and i want to build a multiple buttons like on link.
Can anybody help me .It will be very helpful to understand statements and components .
http://noxious-ornament.surge.sh/
i try to write something like this but i don't know how to continue.
import React, { Component } from 'react'
import './Ar.css';
class Ar extends Component {
constructor() {
super();
this.state = {
buttonPressed: 0
// 0 could be your default view
}
}
handleClick = (button) => {
this.setState({ buttonPressed: button })
}
render() {
return(
<div>
<button
className='button1'
onClick={() => this.handleClick(1)}
> BUTTON 1
</button>
<button
className='button2'
onClick={() => this.handleClick(1)}
> BUTTON 2
</button>
<button
className='button2'
onClick={() => this.handleClick(1)}
> BUTTON 3
</button>
}
</div>
)
}
}
export default Ar
This is a start. Next I'd add react-router-dom so you can load the SomePage component.
const {Component} = React;
function SomePage(props){
return (
<div>
Button {props.value} has been pressed!
<button>back</button>
</div>
)
};
class App extends Component {
constructor() {
super();
this.state = {
buttonPressed: 0,
buttonCount: [1,2,3,4,5]
}
}
handleClick = (event) => {
this.setState({ buttonPressed: event.target.id });
}
render() {
return(
<div>
{this.state.buttonCount.length > 0 ? this.state.buttonCount.map((item,index) => (
<button id={item} key = {index} onClick={()=>this.handleClick} className={`button${item}`}>
{item}
</button>
))
: null
}
</div>
)
}
}
// Render
ReactDOM.render(
<App />,
document.getElementById("react")
);
.button1 {
background-color: green;
}
.button2 {
background-color: blue;
}
.button3 {
background-color: red;
}
.button4 {
background-color: yellow;
}
.button5 {
background-color: purple;
}
<div id="react"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
You can have a state variable in the type of array:
this.state = {
buttonPressed: 0,
burronArray:[
{
id : 1,
name : "Button 1"
},
{
id : 2,
name : "Button 2"
},
]
}
and in the render function:
render() {
return(
<div>
{this.state.buttonArray.length > 0 ? buttonArray.map((button, index) => return(
<button
key={index}
value = {button.id}
className='button1'
onClick={() => this.handleClick(1)}
> {button.name}
</button>
)) : null}
</div>
)
}
When I type something in my textarea, and then click on the button, this new element is stocked inside an array and displayed in a list in my react app. I want the array's elements to be crossed when I click on them.
I've written a function to change the state of 'crossed' to its opposite when i click on the element, and then the style of the elements would change depending on whether it's true or false.
app.js:
import React from 'react';
import Tasks from './tasks.js';
import Item from './component.js';
import './App.css';
class App extends React.Component {
state = {
todolist: [],
crossed: false
}
addData(val) {
this.setState({ todolist: this.state.todolist.concat(val) },
() => console.log(this.state.todolist))
}
cross() {
this.setState({ crossed: !this.state.crossed },
() => console.log(this.state.crossed))
}
render() {
return (
<div className="App">
<Tasks onClick={value => this.addData(value)} />
{
(this.state.crossed) ? (<ul>
{this.state.todolist.map((e) => {
return <Item
item={e}
onClick={(e) => this.cross(e)}
style={{ textDecoration : 'line-through' }} />}
)
}
</ul>) : (
<ul>
{this.state.todolist.map((e) => {
return <Item
item={e}
onClick={(e) => this.cross(e)}
/>}
)
}
</ul>
)
}
</div>
);
}
}
export default App;
component.js:
import React from 'react'
class Item extends React.Component{
render(){ return(
<li onClick={this.props.onClick} style={this.props.style}>{this.props.item}
</li>
);
}}
export default Item
tasks.js :
import React from 'react'
class Tasks extends React.Component {
constructor(props) {
super(props)
this.state = {
value: '',
}
}
handleChange = e => {
this.setState({ value: e.target.value })
}
render() {
return (<div>
<textarea value={this.state.value} onChange={this.handleChange} ></textarea>
<button onClick={() => this.props.onClick(this.state.value)}>Add task</button>
</div>)
}
}
export default Tasks
I want each element to be crossed on its own when I click on it, but all the elements get crossed when I click on any one of them.
You should have some key for each object to differentiate,
addData(val) {
const tempObj = {
val: val,
crossed: false
}
this.setState({ todolist: this.state.todolist.concat(tempObj) },
() => console.log(this.state.todolist))
}
Now you will have crossed key for each object. I have not run the code, but this should work.
cross = e => {
e.crossed = !e.crossed;
}
(
<ul>
{this.state.todolist.map(e => {
return <Item
item={e}
onClick={(e) => this.cross(e)}
style={e.crossed && { textDecoration : 'line-through' }} />} // use ternary operator or this kind of && condition here
)
}
</ul>
)
I would like to change current li item color when I click it.
How to add prop to item(using array map), when I click it? I use styled-components
const Li = styled.li`
color: ${props => (props.checked ? "red" : "green")};
`;
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: "",
items: []
};
}
render() {
const ShowItems = this.state.items.map((item, index) => {
return (
<Li key={index}>
{item}
<button onClick={() => this.deleteItemHandler(index)}> Delete</button>
</Li>
);
});
return (
<Wrapper>
<AddItem
addItemHandler={this.addItem}
InputValue={this.state.value}
InputValueHandler={this.inputValue}
/>
{ShowItems}
</Wrapper>
);
}
}
Check out this code working on CodeSandBox
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import styled from "styled-components";
const Li = styled.li`
color: ${props => (props.checked ? "red" : "green")};
`;
class App extends Component {
state = {
value: "",
items: [],
selected: -1
};
handleChange = e => {
this.setState({
[e.currentTarget.name]: e.currentTarget.value
});
};
handleAdd = () => {
const { items, value } = this.state;
this.setState({
items: [...items, value],
value: ""
});
};
handleRemove = index => {
const { items, selected } = this.state;
items.splice(index, 1);
if (index < selected) index = selected - 1;
if (index === selected) index = -1;
if (index > selected) index = selected;
this.setState({
items: items,
selected: index
});
};
handleActiveItem = index => {
this.setState({ selected: index });
};
render() {
const { value, items, selected } = this.state;
return (
<div>
<input
type="text"
value={value}
name="value"
onChange={this.handleChange}
/>
<button
style={{ margin: "0px 5px" }}
disabled={!value}
className="btn btn-sm btn-success"
onClick={this.handleAdd}
>
+
</button>
<ul className="li">
{items.map((item, index) => (
<Li key={index} checked={selected === index}>
<span onClick={() => this.handleActiveItem(index)}>{item}</span>
<button
style={{ margin: "1px 5px" }}
className="btn btn-sm btn-danger"
onClick={() => this.handleRemove(index)}
>
X
</button>
</Li>
))}
</ul>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Ignore the handlers if you don't need them. Thanks to this effort I learnt about styled-components and discovered CodeSandBox.
EDIT :
Added a <span> inside <li> to avoid nested onClick, previously <li> (parent) and <button> (child) both had onClick attribute. On button Click two onClick events were fired resulting in unexpected behaviour in some use cases. You must correct this in your code.
Added logic to keep item selected when an item before it is deleted.
Added button validation to avoid adding empty string/items in list.
Also updated CodeSandBox Code to reflect above changes.
So you need keep track of the active index, and use it too change the color of the active component color.
state ={
activeIndex: void 0
}
const Li = styled.li`
color: ${props => props.checked ? "red" : "green"};
;`
deleteItemHandler = (index) => {
this.setState({
activeIndex: index
})
}
render() {
const ShowItems = this.state.items.map((item, index) => {
return (
<Li key={index} checked={index === this.state.activeIndex} > {item} < button onClick={() => this.deleteItemHandler(index)
}> Delete</button ></Li >
)
})
return (
<Wrapper>
<AddItem
addItemHandler={this.addItem}
InputValue={this.state.value}
InputValueHandler={this.inputValue}
/>
{ShowItems}
</Wrapper>
);
Try this
const Li = styled.li`
color: ${props => props.checked ? "red" : "green"};
;`
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: "",
items: [],
currentChecked: null
};
}
render() {
const ShowItems = this.state.items.map((item, index) => {
return (
<Li key={index} checked={index === this.state.currentChecked} >
{item}
<button onClick={() => this.setState({currentChecked: index})}>Delete</button >
</Li >
)
})
return (
<Wrapper>
<AddItem
addItemHandler={this.addItem}
InputValue={this.state.value}
InputValueHandler={this.inputValue}
/>
{ShowItems}
</Wrapper>
);
In my navbar, I have a button that will display a submenu (list of items) when clicked. Each item is their own child component and when clicked I want them to fire an event. The onClick event listener is not responding at all. However, other mouse events do apply (onMouseEnter, onMouseOut etc). Anyone might know what's up?
Child Component: NotificationItem.js
import React from "react"
import { connect } from "react-redux"
import { updateNotification } from "../../actions/notificationActions"
class NotificationItem extends React.Component{
constructor(props){
super(props)
this.handleOnClick = this.handleOnClick.bind(this)
}
handleOnClick = (event) => {
console.log("clicked")
// let notificationId = this.props.notification._id
// this.props.updateNotification(notificationId)
}
render(){
let {avatar, description, seen} = this.props.notification
return(
<div
onClick={this.handleOnClick}
className="d-flex notification-wrapper"
style={ seen ? (
{ width: "250px", whiteSpace: "normal", padding: "0.5rem" }
):( { width: "250px", whiteSpace: "normal", padding: "0.5rem", backgroundColor: "#d7e2f4" }
)
}
>
<div>
<img src={avatar} style={{ width: "25px"}} className="mr-2 rounded-circle"/>
</div>
<div>
{description}
</div>
</div>
)
}
}
Parent component: NotificationFeed.js
import React from "react"
import { connect } from "react-redux"
import NotificationItem from "./NotificationItem"
class NotificationFeed extends React.Component{
constructor(props){
super(props)
}
render(){
let notifications = this.props.notification.notifications
return(
<div className="dropdown-menu">
{notifications.map((notification, index) => {
return(
<div key={index}>
<NotificationItem notification={notification}/>
</div>
)
})}
</div>
)
}
}
const mapStateToProps = (state) => {
return{
notification: state.notification
}
}
export default connect(mapStateToProps)(NotificationFeed)
Edit: Something I noticed that might be of help. I'm using a bootstrap class to create this dropdown toggle-effect. When clicking on one of the items, the submenu closes immediately, without firing my desired event handler on the component.
<span className="dropdown" id="notifications-dropdown">
<Link to="#" className="nav-link text-light dropdown-toggle" data-toggle="dropdown">
<span
key={Math.random()}
>
<i className="fa fa-bell"></i>
</span> { windowWidth < 576 && "Notifications"}
<NotificationFeed/>
</Link>
</span>
For those still interested, this was a problem with Bootstrap. Because the elements were created inside a Bootstrap dropdown it had some logic I couldn't see. Whenever I would click on an element, the dropdown closes before the event-handler would even fire.
Opted, to create my own dropdown instead. Thanks all!
You created an arrow function, you do not need to bind it in the constructor
import React from "react"
import { connect } from "react-redux"
import { updateNotification } from "../../actions/notificationActions"
class NotificationItem extends React.Component{
state = {}
handleOnClick = (event) => {
console.log("clicked")
}
//or do not use arrow function then bind in the constructor
//constructor(props) {
//super(props);
//this.handleOnClick = this.handleOnClick.bind(this)
//}
// handleOnClick(event) {
// console.log("clicked")
// }
render(){
let {avatar, description, seen} = this.props.notification
return(
<div
onClick={this.handleOnClick}
className="d-flex notification-wrapper"
style={ seen ? (
{ width: "250px", whiteSpace: "normal", padding: "0.5rem" }
):( { width: "250px", whiteSpace: "normal", padding: "0.5rem", backgroundColor: "#d7e2f4" }
)
}
>
<div>
<img src={avatar} style={{ width: "25px"}} className="mr-2 rounded-circle"/>
</div>
<div>
{description}
</div>
</div>
)
}
try this
onClick={ (e) => this.handleOnClick(e)}
Try change your code, now it's like method:
handleOnClick(event){
console.log("clicked")
}
I am trying to make an application using reactjs.below is the code which present in my main app.js:
class App extends Component {
return (
<div>
<ExampleTable
header={() => <TopBar/>}
/>
<AddExampleModal/>
<ChartModal/>
<CompatibilityAlert/>
</div>
)
}
}
where Top Bat,AddExampleModal , ChartModal and CompatibilityAlert are loaded from other js files.
Chartmodal contains:
class ChartModal extends Component{
constructor(props){
super(props)
}
render(){
return(
<Modal
onOk={()=>console.log('ok')}
onCancel={()=>console.log('cancel')}
visible={true}
okText={'ok'}
cancelText={'cancel'}
confirmLoading={false}
title="Intent distribution chart"
>
<h1>HOWDY</h1>
<TreeMap
data={chartData}
width={400}
valueUnit={'count'}
/>
</Modal>
)
}
}
Topbar contains :
class TopBar extends Component {
render{
return (
<Button
style={styles.button}
type='primary'
// onClick={() => changechartshow()}
>
Show Graph
</Button>
)
}
}
The thing is that in the app file,i want to toggle the visibility of chartmodal using the button in the topbar.
App
class App extends Component {
constructor() {
this.state = {
isVisible: true
}
}
toggleVisibility = () => this.setState({isVisible: !this.state.isVisible})
render () {
const {isVisible} = this.state;
return (
<div>
<ExampleTable
header={() => <TopBar toggleVisibility =
{this.toggleVisibility.bind(this)}
/>}
<AddExampleModal/>
<ChartModal isVisible={isVisible}/>
<CompatibilityAlert/>
</div>
);
}
}
TopBar
class TopBar extends Component {
render{
return (
<Button
style={styles.button}
type='primary'
onClick={() => this.props.toggleVisibility()}
>
Show Graph
</Button>
)
}
}
ChartModal - Pass the state to visible attribute
class ChartModal extends Component{
constructor(props){
super(props)
}
render(){
return(
<Modal
onOk={()=>console.log('ok')}
onCancel={()=>console.log('cancel')}
visible={this.props.isVisible}
okText={'ok'}
cancelText={'cancel'}
confirmLoading={false}
title="Intent distribution chart"
>
<h1>HOWDY</h1>
<TreeMap
data={chartData}
width={400}
valueUnit={'count'}
/>
</Modal>
)
}
}
You can add a state in your App component and pass an handler to update the state from the TopBar component. Based on this state you can toggle the visibility of ChartModal.
class App extends Component {
state = {
isVisible: true
}
toggleVisibility = () => {
this.setState(prevState => ({isVisible: !prevState.isVisible}))
}
return (
<div>
<ExampleTable
header={() => <TopBar toggleVisibility={this.toggleVisibility}/>}
/>
<AddExampleModal/>
{this.state.isVisible ? <ChartModal/>: null }
<CompatibilityAlert/>
</div>
)
}
}
Now in your TopBar you will call this function as
class TopBar extends Component {
render{
return (
<Button
style={styles.button}
type='primary'
onClick={() => this.props.toggleVisibility()}
>
Show Graph
</Button>
)
}
}
Read the React docs here on Lifting the state up for a detailed explanation