Reputation: 311
I used jquery in the function checkall to check/uncheck all the checkboxes in a specific column for a fixed-data-table. I wonder if this is the best approach or is there a "react-way" of doing this?
'use strict';
var React = require('react/addons');
var Table = require('fixed-data-table').Table;
var Column = require('fixed-data-table').Column;
// Table data as a list of array.
var rows = [
['a1', 'b1', 'c1'],
['a2', 'b3', 'c2'],
['a3', 'b3', 'c3'],
];
function checkBox(data){
return (
<input type="checkbox" value={data} className="kill-checkbox" />
);
}
function rowGetter(rowIndex) {
return rows[rowIndex];
}
// Fixed data tables (Facebook) requirement:http://facebook.github.io/fixed-data-table/
require('../../styles/fixed-data-table.css');
var TableTester = React.createClass({
render: function () {
return (
<div>
<label>Check All</label> <input type="checkbox" id="check-all" onClick={this.checkall} />
<Table rowsCount={rows.length} width={1000} height={300} headerHeight={50} rowHeight={50} rowGetter={rowGetter}>
<Column label="Col 1" width={500} dataKey={0} />
<Column label="Col 2" width={500} dataKey={1} cellRenderer={checkBox} align="center" />
</Table>
</div>
);
},
checkall:function(){
var checked = $("#check-all").is(':checked');
$(".kill-checkbox").each(function(){
$(this).prop('checked', checked);
});
},
});
module.exports = TableTester;
Upvotes: 0
Views: 5992
Reputation: 311
As promised I have a working example based on the solution/explanation provided in a fixed-data-table issue: https://github.com/facebook/fixed-data-table/issues/70
'use strict';
var React = require('react/addons');
var Table = require('fixed-data-table').Table;
var Column = require('fixed-data-table').Column;
var dataKey = 1; // key to store in selected in the sets below it represents the values [b1|b2|b3] as in index 1
// Fixed data tables (Facebook) requirement:http://facebook.github.io/fixed-data-table/
require('../../styles/fixed-data-table.css');
var TableTester = React.createClass({
getInitialState: function(){
return ({
selected:[],
rows: [
['a1', 'b1', 'c1'],
['a2', 'b2', 'c2'],
['a3', 'b3', 'c3'],
]
})
},
render: function () {
var data = this.state.rows;
return (
<div>
<label>Check All</label> <input type="checkbox" onClick={this._toggleAll} />
<Table rowsCount={data.length} rowGetter={this._rowGetter} onRowClick={this._onRowSelect} width={1000} height={300} headerHeight={50} rowHeight={50}>
<Column label="Col 1" width={500} dataKey={0} />
<Column label="Col 2" width={500} dataKey={dataKey} align="center"
cellRenderer={(value) => <input type="checkbox" value={value} checked={this.state.selected.indexOf(value) >= 0} onChange={() => {}} />}/>
</Table>
</div>
);
},
_toggleAll:function(e){
var newSet = [];
if (e.target.checked) {
this.state.rows.forEach(function(columns){
newSet.push( columns[1] );
});
}
this.setState({
selected: newSet
});
},
_onRowSelect: function(e, index) {
var value = this.state.rows[index][dataKey];
var newSet = this.state.selected;
if ( newSet.indexOf(value) < 0 ) { // does not exist in list
newSet.push(value);
} else {
newSet.splice(newSet.indexOf(value), 1);
}
this.setState({
selected: newSet
});
},
_rowGetter: function(rowIndex){
return this.state.rows[rowIndex];
}
});
module.exports = TableTester;
Upvotes: 1
Reputation: 62813
It depends what a checkbox being checked or unchecked means in your application and when you need this information. Doing it this way effectively puts state into the DOM and you will have to go back to the DOM to get a hold of it when you need that information later.
Another way to do this would be to have some data which represents or can be used to derive the checked-ness of each checkbox and use this to set its checked
prop. You would then need to implement the appropriate event handlers to update the data appropriately based on the user's actions.
e.g., if you're displaying a grid of checkboxes which have associated values, you might have a selectedValues
list. We'll put it in the component's own state for convenience of creating example code, but this might be coming in as a prop, or live in a store, or...
getInitialState() {
return {
selectedValues: []
}
},
You could then derive the checked
state of each checkbox using the list of selected values:
renderCheckbox(data) {
var checked = this.state.selectedvalues.indexOf(data) != -1
return <input type="checkbox" value={data} checked={checked}/>
}
in render(): cellRenderer={this.renderCheckbox}
But now your checkboxes are read-only, because you haven't implemented changing selectedValues
in response to an event on them, so let's do that:
_onCheckboxChange(e) {
var {selectedValues} = this.state
var {checked, value} = e.target
if (checked) {
selectedValues.push(value)
}
else {
selectedValues.splice(selectedValues.indexOf(value), 1)
}
this.setState({selectedValues})
},
renderCheckbox(data) {
var checked = this.state.selectedValues.indexOf(data) != -1
return <input type="checkbox" value={data} checked={checked} onChange={this._onCheckboxChange}/>
}
Now to implement something like a select/deselect all toggle, you would need to implement an event handler which makes the appropriate data changes and causes the component to re-render:
_onCheckAll(e) {
var selectedValues
if (e.target.checked) {
// Set all the available values as selected - using the rows variable
// from your question to put something meaningful here.
selectedValues = rows.reduce((all, row) => all.concat(row))
}
else {
selectedValues = []
}
this.setState({selectedValues})
}
I suppose that means the "React way" is to model your UI in terms of data, rather than the end result you want to see, in this case it's "which of the values I'm displaying are selected?" versus "which checkboxes are checked?"
Upvotes: 1