I have a select all component rendering in my table header, I would like it to check all of the checkboxes on the page when checked, if one of the checkboxes is unchecked I would like the select all to unselect too:
var SelectAll = React.createClass({
handler: function(e) {
e.target.value;
e.preventDefault();
channel.publish({
channel: "contact",
topic: "selectAll",
data: {
contacts: this.props.data
}
});
},
render: function() {
console.log(this.props.data.children);
var id = this.props.contacts;
var isSelected = this.props.data.isSelected;
return (
<div className="contact-selector">
<input type="checkbox" checked={isSelected}
onChange={this.handler} />
</div>
);
},
});
My checkboxes are rendered in each table row:
var ContactSelector = React.createClass({
getInitialState: function() {
return {
selectedContacts:[]
};
},
handleChange: function(e) {
var id = e.target.attributes['data-ref'].value;
if (e.target.checked === true){
contactChannel.publish({
channel: "contact",
topic: "selectedContact",
data: {
id: id
}});
} else{
contactChannel.publish({
channel: "contact",
topic: "deselectedContact",
data: {
id: id
}});
}
},
render: function() {
var id = this.props.data.id;
var isSelected = this.props.data.IsSelected;
return (
<div className="contact-selector">
<input type="checkbox"
checked={isSelected} data-ref={id}
onClick={this.handleChange} />
</div>
);
}
});
Can anyone please tell me how to setup the check all? Using state or refs etc
Related
I'm trying to create a menu where the user should create a character details but I'm having an issue to update the Options states through an input of a child.
var Name = React.createClass({
render: function(){
return(
<input type="text"/>
)
}
});
var Options = React.createClass({
getInitialState: function(){
return{
name: ''
}
},
render: function(){
return (
<div>
Name: <Name onChange={this.updateName} value={this.state.name} />
</div>
)
},
updateName: function(evt){
this.setState({
name: evt.target.value
});
}
});
How can I go about updating the Option states using the input from Name?
you need onChange function on the Name component as well, that sends the value to the parent component
Try this:
var Name = React.createClass({
onUpdate: function(evt) {
this.props.onChange(evt);
}
render: function(){
return(
<input type="text" onChange={this.onUpdate} value={this.props.value}/>
)
}
});
var Options = React.createClass({
getInitialState: function(){
return{
name: ''
}
},
render: function(){
return (
<div>
Name: <Name onChange={this.updateName} value={this.state.name} />
</div>
)
},
updateName: function(evt){
this.setState({
name: evt.target.value
});
}
});
Component Communication in React
Refer this link to know what are the ways to communicate between React components.
I'm currently "testing the waters" with Reactjs. Based on their docs, I have whipped up a small project that I'm stuck with. So far, when the checkbox is checked, the state changes but....not sure how to change a state unchecked:
var Foo = React.createClass{(
getInitialState: function() {
return {
location: true,
}
},
onClick: function() {
this.setState({ location: false });
},
render: function() {
var inlineStyles = {
display: this.state.location ? 'block' : 'none'
};
return (
<div>
<input type="checkbox"
onClick={this.onClick}
/> show / hide bar
<hr />
<div style={inlineStyles}>
<p>bar</p>
</div>
</div>
);
}
)};
Do I need to use an if statement for the sort of thing I want? I need to this.setState.location: true when unchecked.
You need to read the state of the checkbox during a click, and apply that to your React state.
var Foo = React.createClass({
render: function() {
return <input type="checkbox" onClick={this.onClick} checked={!this.state.location}></input>
},
onClick: function(e) {
this.setState({location: !e.target.checked});
},
getInitialState: function() {
return {
location: true
};
}
});
In my React.js to-do app, I'm trying to enable the return key to submit an item from my TextInput component to my ToDoList component. Right now the TextInput.inputSubmit method just console.logs the input value, but I'm wondering if I can have it trigger a prop (enter={that.addToDo}) inside of ToDoList. Or is there a better way?
JSFiddle
Edit: improved JSFiddle (courtesy of knowbody)
/** #jsx React.DOM */
var todos = [{text: "walk dog"}, {text: "feed fish"}, {text: "world domination"}, {text: "integrate return key"}];
var TextInput = React.createClass({
getInitialState: function() {
return {text: ''};
},
inputSubmit: function() {
//I think I want to trigger ToDoList's addToDo method from here?
console.log(this.refs.inputEl.getDOMNode().value);
this.setState({text: ''});
},
handleChange: function(evt) {
this.setState({text: evt.target.value});
},
handleKeyDown: function(evt) {
if (evt.keyCode === 13 ) {
return this.inputSubmit();
}
},
render: function() {
return (
<input value={this.state.text} ref="inputEl" onChange={this.handleChange} onKeyDown={this.handleKeyDown}/>
)
}
});
var SubmitButton = React.createClass({
render: function(){
return (
<button onClick={this.props.click}> Add </button>
)
}
});
var ToDo = React.createClass({
render: function(){
return (
<div>
<button onClick={this.props.click}>X</button>
<span> - {this.props.text}</span>
</div>
)
}
});
var ToDoList = React.createClass({
getInitialState: function (){
return {
todos: this.props.todos.splice(0)
}
},
deleteToDo: function(todo){
this.state.todos.splice(this.state.todos.indexOf(todo), 1);
this.setState({todos: this.state.todos});
},
addToDo: function(){
this.state.todos.push({text: this.refs.textIn.refs.inputEl.getDOMNode().value});
this.setState({
todos: this.state.todos
});
this.refs.textIn.setState({text: ''});
},
render: function(){
var that = this;
return (
<div>
{this.state.todos.map(function(todo) {
return (
<ToDo text={todo.text} click={that.deleteToDo.bind(null, todo)} />
)
})}
<br/>
<TextInput ref="textIn" enter={that.addToDo} />
<SubmitButton click={that.addToDo} />
</div>
)
}
});
React.renderComponent(<ToDoList todos={todos} />, document.body);
Your code is a bit messy but a quick fix will be to add:
this.props.enter(this.refs.inputEl.getDOMNode().value);
where your console.log() is. I will edit my answer with the full explanation once I'm on my laptop
I am learning ReactJS and trying to develop small CRUD form using it. At this point, I am trying to set input values from other sibling component to perform update.
So, if I click on edit button in first row on grid, Organzation Name and Description input boxes should get "abc com" and "company Abc" values respectively.
var OrganizationHandler = React.createClass(
render: function() {
return (
<div>
<OrganizationAPP onOrganizationSubmit=this.handleOrganizationSubmit} />
<OrganizationList external_DeleteOrganization={this.DeleteOrganizationFromServer} data= {this.state.data} />
</div>
);
}
});
var OrganizationList = React.createClass({
internal_DeleteOrganization: function(id) {
this.props.external_DeleteOrganization(id);
},
render: function() {
var results = this.props.data;
var parsed_results = results.objects;
var that = this;
var organizations = parsed_results.map(function(organization){
return <Organization onDeleteOrganization={that.internal_DeleteOrganization} id={organization.id} name={organization.name} description={organization.description} />
});
return(
<div>
{organizations}
</div>
);
}
});
var Organization = React.createClass({
handleDeleteClick: function() {
console.log(this.props);
this.props.onDeleteOrganization(this.props.id);
},
handleEditClick: function () {
alert(this.props.name);
},
render: function() {
return (
<div className="row">
<div className="small-2 large-2 columns">{this.props.id}</div>
<div className="small-4 large-4 columns">{this.props.name}</div>
<div className="small-4 large-4 columns"> this.props.description}</div>
<div className="small-2 large-2 columns">
<input type="button" onClick={this.handleDeleteClick} data-order={this.props.id} value="Delete" />
<input type="button" onClick={this.handleEditClick} data-order={this.props.id} value="Edit" />
</div>
</div>
);
}
});
var OrganizationAPP= React.createClass({
getInitialState: function() {
return {name: '', description:''};
},
onChangename: function(e) {
this.setState({name: e.target.value});
},
onChangedescription: function(e) {
this.setState({description: e.target.value});
},
handleSubmit: function() {
var name = this.refs.name.getDOMNode().value.trim();
var description = this.refs.description.getDOMNode().value.trim();
if (!description || !name) {
return false;
}
this.props.onOrganizationSubmit('{"name":"' + name +'", "description": "' + description +'"}');
this.refs.name.getDOMNode().value = '';
this.refs.name.getDOMNode().value = '';
this.setState({name: '', description: ''});
return false;
},
render: function() {
return (
<div>
<h1>Organization Setup:</h1>
<form onSubmit={this.handleSubmit}>
<div className="row">
<div className="small-12 large-3 columns">
<label>Organization Name:</label>
<input type="text" ref="name" required value={this.props.name} onChange={this.onChangename}/>
</div>
</div>
<div className="row">
<div className="small-12 large-7 columns">
<label>description:</label>
<input type="text" required ref="description" value={this.props.description} onChange={this.onChangedescription} />
</div>
</div>
<div className="row">
<div className="small-2 large-3 columns">
<button type="submit"> Add </button>
</div>
</div>
</form>
</div>
)
}
});
I have successfully performed addition and deletion operations but I don't know how can I set values to be edit in input boxes from sibling component. Please let me know if you don't understand anything as I just started learning reactjs and I know my code is not up to the mark.
Here is an example list editing app where editing an item content is done with a parent input (could easily be a sibling).
/** #jsx React.DOM */
//React is for rendering our app UI.
//Not for writing the app.
//So the first step is building out your logic in whatever you prefer.
//That could be Backbone, some other framework, or plain JS as we do here.
//our app
var app = {
//we'll tell this listener when we change
listener: null,
//a cheap way of creating IDs for our new data
nextId: 3,
//pre-populate our data
rows: [
{id: 1, name: "entry 1"},
{id: 2, name: "entry 2"}
],
//what data are we focused on
focusedId: 1,
//add a new row of data and set it to focused
addRow: function () {
var id = this.nextId++;
this.rows.push({id: id, name: ("entry " + id)});
this.setFocusedId(id);
},
//get the name property given the data id
getName: function(id){
return _.findWhere(this.rows, {id: id}).name;
},
//update the name property of the currently focused data
updateName: function (name) {
var id = this.focusedId;
_.findWhere(this.rows, {id: id}).name = name;
this.listener.changed();
},
//set the focused data
setFocusedId: function (id) {
this.focusedId = id;
this.listener.changed();
},
};
//a row component
var Row = React.createClass({
render: function () {
if (this.props.focused) {
return <span>Value: {this.props.name} [editing]</span>;
} else {
return <span>
Value: {this.props.name}
[<a href='#' onClick={this.props.focus}>edit</a>]
</span>;
}
}
});
//the main view
var View = React.createClass({
//our state is the app
getInitialState: function () {
return {
app: app
};
},
//before we render, start listening to the app for changes
componentWillMount: function () {
this.state.app.listener = this;
},
//update if the app tells us it changed
changed: function () {
this.forceUpdate();
},
//a handler we'll use for input fields
textChanged: function (event) {
this.state.app.updateName(event.target.value);
},
//let's render
render: function () {
var app = this.state.app;
//build an array of row components
var rows = _.map(app.rows, function (row) {
var focus = function () {
app.setFocusedId(row.id);
};
//the actual row component
//give the row a unique id
//give it a name, the focus handler function,
//and tell it if it has the current focus
return <li key={row.id}>
<Row
name={row.name}
focused={row.id == app.focusedId}
focus={focus}
/>
</li>;
});
//the main app view
return <div>
EDIT:
<input
type="text"
value={app.getName(app.focusedId)}
onChange={this.textChanged}
/>
<ul>{rows}</ul>
<a href="#"
onClick={function(){app.addRow()}}>
add row
</a>
</div>;
}
});
React.renderComponent(
<View />
, document.body);
Here is a working example:
http://jsbin.com/laxejufila/2/edit
I'm having a little problem while trying to create a checkbox that selects and deselects other individual checkboxes (select/deselect all) with React. I've read http://facebook.github.io/react/docs/forms.html and discovered that there are differences between controlled and not-controlled <input>s. My test code is as follows:
var Test = React.createClass({
getInitialState: function() {
return {
data: [
{ id: 1, selected: false },
{ id: 2, selected: false },
{ id: 3, selected: false },
{ id: 4, selected: false }
]
};
},
render: function() {
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} />
{d.id}
<br />
</div>
);
});
return (
<form>
<input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector
<br />
{checks}
</form>
);
},
__changeSelection: function(e) {
var id = e.target.getAttribute('data-id');
var state = this.state.data.map(function(d) {
return {
id: d.id,
selected: (d.id === id ? !d.selected : d.selected)
};
});
this.setState({ data: state });
},
__changeAllChecks: function(e) {
var value = this.refs.globalSelector.getDOMNode().checked;
var state = this.state.data.map(function(d) {
return { id: d.id, selected: value };
});
this.setState({ data: state });
}
});
React.renderComponent(<Test />, document.getElementById('content'));
The "Global selector" works as expected: when selected, all other checks are selected. The problem is that the __changeSelection() handler is not fired when one of the other checkboxes are clicked.
I don't know what is the proper way to make this work. Maybe React model is not the best one to model this kind of interaction? What could I do?
Thanks in advance
In your render function, the scope of this for the checks mapping function is different from render, which is the scope you need for __changeSelection, so this.__changeSelection won't locate a __changeSelection property. If you add a .bind(this) to the end of that mapping function, you can bind it's scope to the same this as render:
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" data-id={d.id} checked={d.selected} onChange={this.__changeSelection} />
{d.id}
<br />
</div>
);
}.bind(this));
On a side note, I would just pass the id to the handler function instead of assigning data-attributes. This will remove the need to locate that element in your handler:
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} />
{d.id}
<br />
</div>
);
}.bind(this));
Then update your __changeSelection function to pass in the id as the first arg and remove the attribute lookup line:
__changeSelection: function(id) {
var state = this.state.data.map(function(d) {
return {
id: d.id,
selected: (d.id === id ? !d.selected : d.selected)
};
});
this.setState({ data: state });
}
Here is an example of it all put together, along with a jsfiddle for you to try it out:
/** #jsx React.DOM */
var Test = React.createClass({
getInitialState: function() {
return {
data: [
{ id: 1, selected: false },
{ id: 2, selected: false },
{ id: 3, selected: false },
{ id: 4, selected: false }
]
};
},
render: function() {
var checks = this.state.data.map(function(d) {
return (
<div>
<input type="checkbox" checked={d.selected} onChange={this.__changeSelection.bind(this, d.id)} />
{d.id}
<br />
</div>
);
}.bind(this));
return (
<form>
<input type="checkbox" ref="globalSelector" onChange={this.__changeAllChecks} />Global selector
<br />
{checks}
</form>
);
},
__changeSelection: function(id) {
var state = this.state.data.map(function(d) {
return {
id: d.id,
selected: (d.id === id ? !d.selected : d.selected)
};
});
this.setState({ data: state });
},
__changeAllChecks: function() {
var value = this.refs.globalSelector.getDOMNode().checked;
var state = this.state.data.map(function(d) {
return { id: d.id, selected: value };
});
this.setState({ data: state });
}
});
React.renderComponent(<Test />, document.getElementById('content'));
If you are dealing with checkboxes you can use the checkedLink attribute. Here is another possible implementation, that makes the global checkbox controlled (instead of uncontrolled in the current answers):
JsFiddle
var Test = React.createClass({
getInitialState: function() {
return {
globalCheckbox: false,
data: [
{ id: 1, selected: false },
{ id: 2, selected: false },
{ id: 3, selected: false },
{ id: 4, selected: false }
]
};
},
changeCheckForId: function(id,bool) {
this.setState(
{
data: this.state.data.map(function(d) {
var newSelected = (d.id === id ? bool : d.selected);
return {id: d.id, selected: newSelected};
}
)});
},
changeCheckForAll: function(bool) {
this.setState({
globalCheckbox: true,
data: this.state.data.map(function(d) {
return {id: d.id, selected: bool};
})
});
},
linkCheckbox: function(d) {
return {
value: d.selected,
requestChange: function(bool) { this.changeCheckForId(d.id,bool); }.bind(this)
};
},
linkGlobalCheckbox: function() {
return {
value: this.state.globalCheckbox,
requestChange: function(bool) { this.changeCheckForAll(bool); }.bind(this)
};
},
render: function() {
var checks = this.state.data.map(function(d) {
return (
<div>
<input key={d.id} type="checkbox" checkedLink={this.linkCheckbox(d)} />
{d.id}
<br />
</div>
);
}.bind(this));
return (
<form>
<input type="checkbox" checkedLink={this.linkGlobalCheckbox()} />Global selector
<br />
{checks}
</form>
);
},
});
It is simpler to use checkedLink=this.linkState("checkboxValue") with LinkedStateMixin if the state to mutate is not deeply nested (like this is the case in this question)
Edit: checkedLink and valueLink are being deprecated but were recommmended in previous versions of React.