I'm new to React.
I'm trying to change the color of one particular "li" that was selected, but instead it changes color of all "li".
Also when another "li" is clicked I want the first "i" to be not active again.
here is the code: http://codepen.io/polinaz/pen/zNJKqO
var List = React.createClass({
getInitialState: function(){
return { color: ''}
},
changeColor: function(){
var newColor = this.state.color == '' ? 'blue' : '';
this.setState({ color : newColor})
},
render: function () {
return (
<div>
<li style={{background:this.state.color}} onClick={this.changeColor}>one</li>
<li style={{background:this.state.color}} onClick={this.changeColor}>two</li>
<li style={{background:this.state.color}} onClick={this.changeColor}>three</li>
</div>
);
}
});
ReactDOM.render(
<List/>,
document.getElementById('app')
);
Since you don't have any identifiers on you list items you activate/deactivate them all every time. You need to reference each of them in a different way, then you can set the color individually. This is one example
var List = React.createClass({
getInitialState: function(){
return { active: null}
},
toggle: function(position){
if (this.state.active === position) {
this.setState({active : null})
} else {
this.setState({active : position})
}
},
myColor: function(position) {
if (this.state.active === position) {
return "blue";
}
return "";
},
render: function () {
return (
<div>
<li style={{background: this.myColor(0)}} onClick={() => {this.toggle(0)}}>one</li>
<li style={{background: this.myColor(1)}} onClick={() => {this.toggle(1)}}>two</li>
<li style={{background: this.myColor(2)}} onClick={() => {this.toggle(2)}}>three</li>
</div>
);
}
});
ReactDOM.render(
<List/>,
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">
<!-- This div's content will be managed by React. -->
</div>
Related
I have
var TestApp = React.createClass({
getComponent: function(){
console.log(this.props);
},
render: function(){
return(
<div>
<ul>
<li onClick={this.getComponent}>Component 1</li>
</ul>
</div>
);
}
});
React.renderComponent(<TestApp />, document.body);
I want to color the background of the clicked list element. How can I do this in React ?
Something like
$('li').on('click', function(){
$(this).css({'background-color': '#ccc'});
});
Why not:
onItemClick: function (event) {
event.currentTarget.style.backgroundColor = '#ccc';
},
render: function() {
return (
<div>
<ul>
<li onClick={this.onItemClick}>Component 1</li>
</ul>
</div>
);
}
And if you want to be more React-ive about it, you might want to set the selected item as state of its containing React component, then reference that state to determine the item's color within render:
onItemClick: function (event) {
this.setState({ selectedItem: event.currentTarget.dataset.id });
//where 'id' = whatever suffix you give the data-* li attribute
},
render: function() {
return (
<div>
<ul>
<li onClick={this.onItemClick} data-id="1" className={this.state.selectedItem == 1 ? "on" : "off"}>Component 1</li>
<li onClick={this.onItemClick} data-id="2" className={this.state.selectedItem == 2 ? "on" : "off"}>Component 2</li>
<li onClick={this.onItemClick} data-id="3" className={this.state.selectedItem == 3 ? "on" : "off"}>Component 3</li>
</ul>
</div>
);
},
You'd want to put those <li>s into a loop, and you need to make the li.on and li.off styles set your background-color.
Two ways I can think of are
var TestApp = React.createClass({
getComponent: function(index) {
$(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
'background-color': '#ccc'
});
},
render: function() {
return (
<div>
<ul>
<li onClick={this.getComponent.bind(this, 1)}>Component 1</li>
<li onClick={this.getComponent.bind(this, 2)}>Component 2</li>
<li onClick={this.getComponent.bind(this, 3)}>Component 3</li>
</ul>
</div>
);
}
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));
This is my personal favorite.
var ListItem = React.createClass({
getInitialState: function() {
return {
isSelected: false
};
},
handleClick: function() {
this.setState({
isSelected: true
})
},
render: function() {
var isSelected = this.state.isSelected;
var style = {
'background-color': ''
};
if (isSelected) {
style = {
'background-color': '#ccc'
};
}
return (
<li onClick={this.handleClick} style={style}>{this.props.content}</li>
);
}
});
var TestApp2 = React.createClass({
getComponent: function(index) {
$(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
'background-color': '#ccc'
});
},
render: function() {
return (
<div>
<ul>
<ListItem content="Component 1" />
<ListItem content="Component 2" />
<ListItem content="Component 3" />
</ul>
</div>
);
}
});
React.renderComponent(<TestApp2 /> , document.getElementById('soln2'));
Here is a DEMO
I hope this helps.
Here is how you define a react onClick event handler, which was answering the question title... using es6 syntax
import React, { Component } from 'react';
export default class Test extends Component {
handleClick(e) {
e.preventDefault()
console.log(e.target)
}
render() {
return (
<a href='#' onClick={e => this.handleClick(e)}>click me</a>
)
}
}
Use ECMA2015. Arrow functions make "this" a lot more intuitive.
import React from 'react';
class TestApp extends React.Component {
getComponent(e, index) {
$(e.target).css({
'background-color': '#ccc'
});
}
render() {
return (
<div>
<ul>
<li onClick={(e) => this.getComponent(e, 1)}>Component 1</li>
<li onClick={(e) => this.getComponent(e, 2)}>Component 2</li>
<li onClick={(e) => this.getComponent(e, 3)}>Component 3</li>
</ul>
</div>
);
}
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));`
If you're using ES6, here's some simple example code:
import React from 'wherever_react_is';
class TestApp extends React.Component {
getComponent(event) {
console.log('li item clicked!');
event.currentTarget.style.backgroundColor = '#ccc';
}
render() {
return(
<div>
<ul>
<li onClick={this.getComponent.bind(this)}>Component 1</li>
</ul>
</div>
);
}
}
export default TestApp;
In ES6 class bodies, functions no longer require the 'function' keyword and they don't need to be separated by commas. You can also use the => syntax as well if you wish.
Here's an example with dynamically created elements:
import React from 'wherever_react_is';
class TestApp extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{name: 'Name 1', id: 123},
{name: 'Name 2', id: 456}
]
}
}
getComponent(event) {
console.log('li item clicked!');
event.currentTarget.style.backgroundColor = '#ccc';
}
render() {
<div>
<ul>
{this.state.data.map(d => {
return(
<li key={d.id} onClick={this.getComponent.bind(this)}>{d.name}</li>
)}
)}
</ul>
</div>
);
}
}
export default TestApp;
Note that each dynamically created element should have a unique reference 'key'.
Furthermore, if you would like to pass the actual data object (rather than the event) into your onClick function, you will need to pass that into your bind. For example:
New onClick function:
getComponent(object) {
console.log(object.name);
}
Passing in the data object:
{this.state.data.map(d => {
return(
<li key={d.id} onClick={this.getComponent.bind(this, d)}>{d.name}</li>
)}
)}
Handling events with React elements is very similar to handling events
on DOM elements. There are some syntactic differences:
React events are named using camelCase, rather than lowercase.
With JSX you pass a function as the event handler, rather than a string.
So as mentioned in React documentation, they quite similar to normal HTML when it comes to Event Handling, but event names in React using camelcase, because they are not really HTML, they are JavaScript, also, you pass the function while we passing function call in a string format for HTML, they are different, but the concepts are pretty similar...
Look at the example below, pay attention to the way event get passed to the function:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
import React from 'react';
class MyComponent extends React.Component {
getComponent(event) {
event.target.style.backgroundColor = '#ccc';
// or you can write
//arguments[0].target.style.backgroundColor = '#ccc';
}
render() {
return(
<div>
<ul>
<li onClick={this.getComponent.bind(this)}>Component 1</li>
</ul>
</div>
);
}
}
export { MyComponent }; // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;
class FrontendSkillList extends React.Component {
constructor() {
super();
this.state = { selectedSkill: {} };
}
render() {
return (
<ul>
{this.props.skills.map((skill, i) => (
<li
className={
this.state.selectedSkill.id === skill.id ? "selected" : ""
}
onClick={this.selectSkill.bind(this, skill)}
style={{ cursor: "pointer" }}
key={skill.id}
>
{skill.name}
</li>
))}
</ul>
);
}
selectSkill(selected) {
if (selected.id !== this.state.selectedSkill.id) {
this.setState({ selectedSkill: selected });
} else {
this.setState({ selectedSkill: {} });
}
}
}
const data = [
{ id: "1", name: "HTML5" },
{ id: "2", name: "CSS3" },
{ id: "3", name: "ES6 & ES7" }
];
const element = (
<div>
<h1>Frontend Skill List</h1>
<FrontendSkillList skills={data} />
</div>
);
ReactDOM.render(element, document.getElementById("root"));
.selected {
background-color: rgba(217, 83, 79, 0.8);
}
<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>
<div id="root"></div>
#user544079 Hope this demo can help :) I recommend changing background color by toggling classname.
import React from 'react';
class MyComponent extends React.Component {
getComponent(event) {
event.target.style.backgroundColor = '#ccc';
// or you can write
//arguments[0].target.style.backgroundColor = '#ccc';
}
render() {
return(
<div>
<ul>
<li onClick={this.getComponent.bind(this)}>Component 1</li>
</ul>
</div>
);
}
}
export { MyComponent }; // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;
You can make use of the React.createClone method. Create your element, than create a clone of it. During the clone's creation, you can inject props. Inject an onClick : method prop like this
{ onClick : () => this.changeColor(originalElement, index) }
the changeColor method will set the state with the duplicate, allowing you sto set the color in the process.
render()
{
return(
<ul>
{this.state.items.map((val, ind) => {
let item = <li key={ind}>{val}</li>;
let props = {
onClick: () => this.Click(item, ind),
key : ind,
ind
}
let clone = React.cloneElement(item, props, [val]);
return clone;
})}
</ul>
)
}
This is a non-standard (but not so uncommon) React pattern that doesn't use JSX, instead putting everything inline. Also, it's Coffeescript.
The 'React-way' to do this would be with the component's own state:
(c = console.log.bind console)
mock_items: [
{
name: 'item_a'
uid: shortid()
}
{
name: 'item_b'
uid: shortid()
}
{
name: 'item_c'
uid: shortid()
}
]
getInitialState: ->
lighted_item: null
render: ->
div null,
ul null,
for item, idx in #mock_items
uid = item.uid
li
key: uid
onClick: do (idx, uid) =>
(e) =>
# justf to illustrate these are bound in closure by the do lambda,
c idx
c uid
#setState
lighted_item: uid
style:
cursor: 'pointer'
background: do (uid) =>
c #state.lighted_item
c 'and uid', uid
if #state.lighted_item is uid then 'magenta' else 'chartreuse'
# background: 'chartreuse'
item.name
This example works -- I tested it locally.
You can check out this example code exactly at my github.
Originally the env was only local for my own whiteboard r&d purposes but I posted it to Github for this. It may get written over at some point but you can check out the commit from Sept 8, 2016 to see this.
More generally, if you want to see how this CS/no-JSX pattern for React works, check out some recent work here. It's possible I will have time to fully implement a POC for this app idea, the stack for which includes NodeJS, Primus, Redis, & React.
I saw some questions speaking about similar issues but somehow I still do not manage to solve my issue so here I am asking for your kind help. I am pretty new to React and would like to send a function from a Parent to a child and then use it from the Child but somehow when I want to use it it says
Uncaught TypeError: Cannot read property 'props' of undefined"
Edited Code after first answers were helping:
var Menu = React.createClass({
links : [
{key : 1, name : "help", click : this.props.changePageHelp}
],
render : function() {
var menuItem = this.links.map(function(link){
return (
<li key={link.key} className="menu-help menu-link" onClick={link.click}>{link.name}</li>
)
});
return (
<ul>
{menuItem}
</ul>
)
}
});
var Admin = React.createClass ({
_changePageHelp : function() {
console.log('help');
},
render : function () {
return (
<div>
<div id="menu-admin"><Menu changePageHelp={this._changePageHelp.bind(this)} /></div>
</div>
)
}
});
ReactDOM.render(<Admin />, document.getElementById('admin'));
Pass a value from Menu function and recieve it in the changePageHelp function and it works.
var Menu = React.createClass({
render : function() {
return (
<div>
{this.props.changePageHelp('Hello')}
</div>
)
}
});
var Admin = React.createClass ({
_changePageHelp : function(help) {
return help;
},
render : function () {
return (
<div>
<div id="menu-admin"><Menu changePageHelp={this._changePageHelp.bind(this)} /></div>
</div>
)
}
});
ReactDOM.render(<Admin />, document.getElementById('admin'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.8/react-dom.min.js"></script>
<div id="admin"></div>
For performance reasons, you should avoid using bind or arrow functions in JSX props. This is because a copy of the event handling function is created for every instance generated by the map() function. This is explained here: https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/jsx-no-bind.md
To avoid this you can pull the repeated section into its own component. Here is a demo: http://codepen.io/PiotrBerebecki/pen/EgvjmZ The console.log() call in your parent component receives now the name of the link. You could use it for example in React Router.
var Admin = React.createClass ({
_changePageHelp : function(name) {
console.log(name);
},
render : function () {
return (
<div>
<div id="menu-admin">
<Menu changePageHelp={this._changePageHelp} />
</div>
</div>
);
}
});
var Menu = React.createClass({
getDefaultProps: function() {
return {
links: [
{key: 1, name: 'help'},
{key: 2, name: 'about'},
{key: 3, name: 'contact'}
]
};
},
render: function() {
var menuItem = this.props.links.map((link) => {
return (
<MenuItem key={link.key}
name={link.name}
changePageHelp={this.props.changePageHelp}
className="menu-help menu-link" />
);
});
return (
<ul>
{menuItem}
</ul>
);
}
});
var MenuItem = React.createClass ({
handleClick: function() {
this.props.changePageHelp(this.props.name);
},
render : function () {
return (
<li onClick={this.handleClick}>
Click me to console log in Admin component <b>{this.props.name}</b>
</li>
);
}
});
ReactDOM.render(<Admin />, document.getElementById('admin'));
I am trying to update the active class when a user clicks on a button. Each time this button is clicked on the next item should have the class name active added and removed from the previous one. Using jQuery I could use the addClass and removeClass methods. Something along these lines would get me started.
$("button").click(function() {
$("ul li").removeClass("active");
var length = $(this).prevAll().length;
$("ul li:eq(" + length + ")").addClass("active");
});
I am not sure how I should go about implementing this using react.
I have set up a JSFIDDLE here.
var App = React.createClass({
getInitialState: function(){
return {
active: 0
}
},
incrementIndex: function() {
this.setState({active : this.state.active + 1});
},
render: function () {
return(
<div>
<ArtistList active={this.state.active} />
<Button increment={this.incrementIndex} />
</div>
)
}
});
var ArtistList = React.createClass({
render: function() {
return(
<ul>
<li className="active">Michael Jackson</li>
<li>Bob Dylan</li>
<li>Kendrick Lamar</li>
</ul>
)
}
});
var Button = React.createClass({
render: function() {
return(
<button onClick={this.props.increment}>next</button>
)
}
})
You can generate the list elements dynamically by iterating over an array containing the list content. Then you can simply compare the passed prop with the current iteration:
var data = ['Michael Jackson', 'Bob Dylan', 'Kendrick Lama'];
var listItems = data.map((value, index) => (
<li
key={value}
className={this.props.active === index ? 'active' : ''}>
{value}
</li>
));
return <ul>{listItems}</ul>;
I would pass in artists as a prop to ArtistList, and then in AristList use a map function to generate a list of li's and use a ternary to figure out if it should be active or not.
have the pen here http://codepen.io/finalfreq/pen/bwoddN
var App = React.createClass({
getInitialState: function(){
return {
active: 0
}
},
incrementIndex: function() {
this.setState({active : this.state.active + 1});
},
render: function () {
const artistList = ['Michael Jackson', 'Bob Dylan', 'Kendrick Lamar']
return(
<div>
<ArtistList artists={artistList} active={this.state.active} />
<Button increment={this.incrementIndex} />
</div>
)
}
});
var ArtistList = React.createClass({
renderArtists: function() {
var self = this;
return this.props.artists.map(function(artist, index) {
var classes = index === self.props.active ? 'active' : '';
return <li key={index + artist} className={classes} > { artist } </li>
});
},
render: function() {
let artists = this.renderArtists();
return(
<ul>
{artists}
</ul>
)
}
});
var Button = React.createClass({
render: function() {
return(
<button onClick={this.props.increment}>next</button>
)
}
})
ReactDOM.render(<App />, document.getElementById('app'));
I have some problems understanding how you interact with element in React after rendering. I currently got this fiddle: https://jsfiddle.net/y7dh3vh5/
var items = ["Afghanistan","Albania","Algeria","Andorra","Angola"....
var RepeatModule = React.createClass({
getDefaultProps: function() {
return { items: [] }
},
render: function() {
var listItems = this.props.items.map(function(item, i) {
return (
<div className="item" key={i}>
<p>{item}</p>
</div>
);
});
return (
<div>
{listItems}
</div>
);
}});ReactDOM.render(<RepeatModule items={items} />, document.getElementById('itemList'));
And I'm looking for a way to highlight a random country when I press the "Highlight random country"-button. Is there an easy way to implement this?
Thanks in advance.
Add state to save highlightedIndex:
getInitialState () {
return {
highlightedIndex: -1
}
},
Add method for button
setNewTarget: function() {
var l = this.props.items.length - 1;
this.setState({
highlightedIndex: this.randomInteger(0, l)
})
},
Put button into return render
return (
<div>
<button onClick={this.setNewTarget}>
Highlight random country
</button>
{listItems}
</div>
);
Live example: https://jsfiddle.net/ufmagg4o/
Just keep your index element in state and compare it in map method. I prefere es6 so i hope you will understand
class Example extends React.Component {
constructor(){
this.state = {
items: ['hello', 'world', 'random', 'highlight'],
index: null
}
this.click = this.click.bind(this);
}
click(){
const items = this.state.items;
const index = Math.floor(Math.random()*items.length);
this.setState({index: index})
}
render(){
const list = this.state.items.map((item,index)=>{
return <p key={index} className={this.state.index === index ? 'item': null}>
{item}
</p>
})
return <div>
<button onClick={this.click}>Click me</button>
{list}
</div>
}
}
React.render(<Example />, document.getElementById('container'));
fiddle example
Thanks!
The key is to keep that button inside React. Don't try to manipulate React components from outside React.
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<div id="itemList">
</div>
.highlighted {
color: white;
background-color: tomato;
}
var items = [
"Afghanistan",
"Albania",
"Algeria",
"Andorra",
"Angola"
]; // etc...
var RepeatModule = React.createClass({
getDefaultProps: function() {
return { items: [] }
},
getInitialState() {
return {highlighted: null};
},
onClickButton() {
this.setState({
highlighted: (Math.random() * this.props.items.length)|0
});
},
render: function() {
var _this = this;
var listItems = this.props.items.map(function(item, i) {
return (
<div className="item" key={i}>
<p className={i == _this.state.highlighted ? 'highlighted' : null}>
{item}
</p>
</div>
);
});
return (
<div>
<button onClick={this.onClickButton}>
Highlight random country
</button>
<div>
{listItems}
</div>
</div>
);
}
});
ReactDOM.render(<RepeatModule items={items} />, document.getElementById('itemList'));
jsfiddle
ES2015 version:
const items = [
"Afghanistan",
"Albania",
"Algeria",
"Andorra",
"Angola"
]; // etc...
class RepeatModule extends React.Component {
static propTypes = {items: React.PropTypes.arrayOf(React.PropTypes.string)};
static defaultProps = {items: []};
state = { highlighted: null };
onClickButton = () => {
this.setState({
highlighted: (Math.random() * this.props.items.length)|0
});
};
render() {
const listItems = this.props.items.map((item, i) => (
<div className="item" key={i}>
<p className={i == this.state.highlighted ? 'highlighted' : null}>
{item}
</p>
</div>
));
return (
<div>
<button onClick={this.onClickButton}>
Highlight random country
</button>
<div>
{listItems}
</div>
</div>
);
}
});
ReactDOM.render(<RepeatModule items={items} />, document.getElementById('itemList'));
According to MDN "You can also do more than one single operation per case, separating them with a comma." The example below works:
var stop = false, age = 23;
age > 18 ? (
alert("1"),
alert("2")
) : (
stop = true,
alert("Sorry, you are much too young!")
);
But I can't seem to do the same in React as seen below. I expect both "Yes" and "No" buttons to be displayed, but it as it only displays the "No" button.
return (
<div className="topcoat-list">
<ul className="topcoat-list__container">
{
notes.map(function (note) {
var title = note.content.substring(0, note.content.indexOf("\n"));
title = title || note.content;
var toggleDeleteDialogs = this.state.isConfirming && note.id === notepad.selectedId;
var disableDelete = this.state.isConfirming && note.id !== notepad.selectedId;
return (
<li key={note.id} onClick={this.onSelectNote.bind(null, note.id)} className="topcoat-list__item">
{title}
{
toggleDeleteDialogs ?
(
<button key={note.id} onClick={this.deleteThisNote.bind(null, note.id)} className="half">Yes</button>,
<button className="half" onClick={this.onCancelDelete}>No</button>
) : (
<button key={note.id} onClick={this.deleteThisNote.bind(null, note.id)} className="full" disabled={disableDelete ? "disabled" : ""}>Delete Note</button>
)
}
</li>
);
}.bind(this))
}
</ul>
</div>
);
Full markup: https://jsfiddle.net/55fvpcLo/
Is my syntax off or could this be done more elegantly?
The fiddle doesn't seem to be working, but I can reproduce the behavior. Although it doesn't raise the Adjacent JSX elements must be wrapped in an enclosing tag error, I suspect that that may be the reason it doesn't work, since adjacent elements is effectively what you're trying to do.
I think the simplest solution is just to wrap the two elements in an enclosing tag rather than parentheses.
You could also return an array of JSX-components, e.g.
{
toggleDeleteDialogs ?
[<Button ... />, <Button ... />] :
<Button .../>
}
#Adam Stone is right that the problem is that there are adjacent JSX elements not wrapped in a closing tag.
That said, you asked for the most elegant way to solve the problem.
I made the following changes to your code:
Used this function to selectively hide JSX elements:
var hideIfFalse=function(boolean){
return boolean? {} : {display : 'none'};
};
which you can use like this:
<div style={hideIfFalse(toggleDeleteDialogs)} />
Separated the logic for rendering the list items into a renderChildren method:
renderChildren:function(notes,classes){
return notes.map(function (note) {
//...
Made a DeleteDialog component. It has reusable functionality with its own rendering logic, and separating it out improves code readability:
var DeleteDialog=React.createClass({
render:function(){
var classes=this.props.classes;
return <div style={hideIfFalse(this.props.toggleDeleteDialogs)}>
<button onClick={this.props.onDelete} className="half">
Yes
</button>,
<button className="half" onClick={this.props.onCancelDelete}>
No
</button>
</div>
}
});
I didn't touch the classSet logic but don't understand what it's supposed to do.
Putting it all together:
var hideIfFalse=function(boolean){
return boolean? {} : {display : 'none'};
};
var notepad = {
notes:
[
{
id: 1,
content: "Hello, world!\nBoring.\nBoring.\nBoring."
},
{
id: 2,
content: "React is awesome.\nSeriously, it's the greatest."
},
{
id: 3,
content: "Robots are pretty cool.\nRobots are awesome, until they take over."
},
{
id: 4,
content: "Monkeys.\nWho doesn't love monkeys?"
}
],
selectedId: 1
};
var DeleteDialog=React.createClass({
render:function(){
var classes=this.props.classes;
return <div style={hideIfFalse(this.props.toggleDeleteDialogs)}>
<button onClick={this.props.onDelete} className="half">
Yes
</button>,
<button className="half" onClick={this.props.onCancelDelete}>
No
</button>
</div>
}
})
var NotesList = React.createClass({
getInitialState: function() {
return {
isConfirming: false
};
},
onSelectNote: function(id) {
notepad.selectedId = id;
},
deleteThisNote: function(noteId) {
if(this.state.isConfirming) {
// actual delete functionality should be here
this.setState({isConfirming: false});
}
else {
this.setState({isConfirming: true});
}
},
onCancelDelete: function() {
this.setState({ isConfirming: false });
},
renderChildren:function(notes,classes){
return notes.map(function (note) {
var title = note.content.substring(0, note.content.indexOf("\n"));
title = title || note.content;
var toggleDeleteDialogs = this.state.isConfirming && note.id === notepad.selectedId;
var disableDelete = this.state.isConfirming && note.id !== notepad.selectedId;
return <li key={note.id}
onClick={this.onSelectNote.bind(null, note.id)}
className="topcoat-list__item">
{title}
<button key={note.id} onClick={this.deleteThisNote.bind(null, note.id)} className="full" disabled={disableDelete ? "disabled" : ""}>Delete Note</button>
<DeleteDialog
toggleDeleteDialogs={toggleDeleteDialogs}
note={note}
onDelete={this.deleteThisNote.bind(null, note.id)}
onCancelDelete={this.onCancelDelete.bind(this)} />
</li>
}.bind(this))
},
render: function() {
var notes = notepad.notes;
var cx = React.addons.classSet;
var classes = cx({
"topcoat-button-bar__button": true,
"full": !this.state.isConfirming,
"half": this.state.isConfirming,
});
return (
<div className="topcoat-list">
<ul className="topcoat-list__container">
{this.renderChildren(notes,classes)}
</ul>
</div>
);
}
});
React.render(<NotesList />, document.getElementById('container'));
JSFiddle: http://jsfiddle.net/55fvpcLo/2/