Closed ZhuQinglei closed 7 years ago
HI @ZhuQinglei, this is a similar issue that you can check it out.
First, I think you can not expand the row when click on row, because you dont enable clickToExpand
in selectRow
props.
Second, following is a example:
class ExpandRow extends React.Component {
constructor(props) {
super(props);
this.state = {
selected: []
};
}
isExpandableRow(row) {
if (row.id < 3) return true;
else return false;
}
handleSaveBtnClick = id => {
// unselect row when click save button
this.setState({ selected: this.state.selected.filter(it => it !== id) });
}
expandComponent = row => {
return (
<div>
<button onClick={ () => this.handleSaveBtnClick(row.id) }>Save me</button>
</div>
);
}
render() {
const onRowSelect = ({ id }, isSelected) => {
if (isSelected) {
this.setState({
selected: [ ...this.state.selected, id ]
});
} else {
this.setState({ selected: this.state.selected.filter(it => it !== id) });
}
return false; //important
};
const selectRowProp = {
mode: 'checkbox',
clickToSelect: true,
clickToExpand: true, // you should add this to trigger selection and expand both on clicking
onSelect: onRowSelect, // manage the selection state
bgColor: 'red',
selected: this.state.selected // set selected as a state data
};
const options = {
expandRowBgColor: 'rgb(242, 255, 163)'
};
return (
<BootstrapTable data={ products }
options={ options }
selectRow={ selectRowProp }
expandableRow={ this.isExpandableRow }
expandComponent={ this.expandComponent }>
<TableHeaderColumn dataField='id' isKey={ true }>Product ID</TableHeaderColumn>
<TableHeaderColumn dataField='name'>Product Name</TableHeaderColumn>
<TableHeaderColumn dataField='price'>Product Price</TableHeaderColumn>
</BootstrapTable>
);
}
}
Third, it's important, the above example can not collapse the row on click save button, I can only unselect the row, I think it's a enhancement for expand row, user should have the ability to handle which row is expandable just like row selection. so I'll do it quickly. As I mentioned in #927, expandable row is a new feature, so there's must be a lots of thing I need to improve, so welcome to tell me if you have any concern.
BTW, you forgot to add react-bootstrap-table
css(react-bootstrap-table-all.min.css
) into your repo, check the README, because I saw a gap between the header and body(Actually, react-bootstrap-table
construct by two different and separated table).
Please let me know if you still have any trouble and I'll improve expandable row as soon as possible. Thanks
Dear @AllenFang ,
Thank you so much for the prompt reply, it is really helpful!
Also, thank you for pointing out clickToExpand! I can expand the row without the prop but my colleague using another computer cannot expand the row on click. We couldn't figure out why and now it must be the clickToExpand in selectRow props I missed out.
However, I found that when I have "selected: this.state.selected" // set selected as a state data , the color will not change. as show below: By commenting out the line the row color will change upon click. Do you have any suggestion on that?
Looking forward to your enhancement for expand row. Thanks again and Happy New Year!
However, I found that when I have "selected: this.state.selected" // set selected as a state data , the color will not change. as show below:
ok~, I'll check this out
Happy New Year
@AllenFang I also found that after import react-bootstrap-table css(react-bootstrap-table-all.min.css), the expanded row is overflowing instead of automatically going to next line. I was using bootstrap grid system for the layout (content on left : buttons on right = 9 : 3). But seems it was override by the (react-bootstrap-table-all.min.css).
Also, the table cell is displaying with overflowing content hidden, but I actually want to display all content in the cell. I could not figure out how to override the css to do this. Do you have any suggestion on that?
@ZhuQinglei,
About the selected: this.state.selected
, I think there's no any problem, make sure the this.state.selected
is an array and which should contain the rowKey.
Second about css problem, It's hard to figure why, I think if a minimal and simple repo for me to reproduce this issue is better.
Anyway, I'll try to do more experiment. thanks
BTW, maybe you can give me the source code of in the expanding row, I wanna see your DOM structure and try it in my local
@ZhuQinglei, you can handle the expanding row in the next version, I'll release it soon, BTW, about the view broke when you import the css of react-bootstrap-table
which I can't reproduce this, following is my screen:
this is the content of expanding row:
expandComponent = row => {
return (
<div className='row'>
<div className='col-md-9'>
<form>
<div className='form-group'>
<label>Email address</label>
<input type='email' className='form-control' id='exampleInputEmail1' placeholder='Email' />
</div>
<div className='form-group'>
<label>Name address</label>
<input type='text' className='form-control'/>
</div>
<div className='form-group'>
<label>Phone</label>
<input type='text' className='form-control'/>
</div>
</form>
</div>
<div className='col-md-3'>
<button className='btn btn-default' onClick={ () => this.handleSaveBtnClick(row.id) }>Save</button>
</div>
</div>
);
}
@AllenFang Thank you so much for the work! Sorry for the late reply, I was a bit busy with other work and I am still new to github, I did not figure out how to create a repo yet.
Here is the comparison: Before I add the css:
After I add the css:
I found that it maybe the form-inline in the expansion. After I removed the form-inline, I would be as the same as your screen. However, I do want to use form-inline in the expansion because I wanted to have small jumbotron and goes to next line responsively.
Here is my code for the expansion: `import React, {Component} from 'react'; import {connect} from 'react-redux'; import {toggleDeleteModal, unSelectClub} from './clubsActions'; import {Activities} from '../../../imports/collections/Activities'; import Input from '../common/Input'; // Similar to Inout component with dropdown options from data of a collection, and I can select options to update selected value accordingly import SearchContacts from '../common/SearchContacts'; import MultiSelectField from '../common/Multiselect'; import SingleSelectField from '../common/SingleSelect';
class ClubDetail extends Component {
constructor(props) {
super(props);
this.state = props.club;
}
handleChange(name, event) {
var change = {};
change[name] = event.target.value;
this.setState(change);
}
updateClub(event) {
event.preventDefault();
const club_id = this.props.club._id;
Meteor.call('clubs.update', club_id, this.state, function (error, result) {
if (error) {
console.log(error);
} else {
// Close the expansion
this.props.unSelectClub(club_id);
// TODO: need to remove the row color highlight
}
}.bind(this));
}
handleActivitiesChange(activities) {
this.setState({
activity_ids: activities
});
}
handleOrganizationChange(organization) {
this.setState({
organization_id: organization
})
}
getContact(contact) {
this.setState({
contact_id: contact
});
}
// Initialise Activities displayed in Multiselect field
getActivityNames() {
var initialValue = [];
this.props.club.activity_ids.map(id => {
const {_id, activity_name} = Activities.findOne({_id: id});
initialValue.push({label: activity_name, value: _id});
});
return initialValue
}
// Initialise Organization displayed in Single-select field
getOrganizationName() {
const {organization_id, organization_name} = this.props.club;
return {label: organization_name, value: organization_id}
}
// Initialise Contact displayed in Single-select field
getContactName() {
const {contact_id, contact_name} = this.props.club;
return {label: contact_name, value: contact_id}
}
render() {
return (
<form className="form-inline background">
<div className="col-md-10">
<Input
type="text"
label="Club Name"
labelPlace="top"
placeholder="Club ID"
value={this.state.club_name}
onChange={this.handleChange.bind(this, 'club_name')}
/>
<SingleSelectField
collection="organizations"
label="Organization Name"
labelPlace="top"
defaultValue={this.getOrganizationName()}
handleSelectChange={this.handleOrganizationChange.bind(this)}
/>
<Input
type="text"
label="Postal Code"
labelPlace="top"
placeholder="Post Code"
value={this.state.post_code}
onChange={this.handleChange.bind(this, 'post_code')}
/>
<Input
type="text"
label="City"
labelPlace="top"
placeholder="city"
value={this.state.city}
onChange={this.handleChange.bind(this, 'city')}/>
<SearchContacts
label="Contact Name"
labelPlace="top"
value={this.getContactName()}
handleSelectChange={this.getContact.bind(this)}/>
<Input
type="text"
label="Phone Number"
labelPlace="top"
value={this.state.phone}
onChange={this.handleChange.bind(this, 'phone')}
placeholder="Phone Number"/>
<MultiSelectField
collection="activities"
label="Activities"
labelPlace="top"
initialValue={this.getActivityNames()}
handleSelectChange={this.handleActivitiesChange.bind(this)}
/>
</div>
<div className="col-md-2">
<div className="btn-trash">
<i className="glyphicon glyphicon-trash"
onClick={this.props.toggleDeleteModal.bind(this)}/>
</div>
<button
onClick={this.updateClub.bind(this)}
className="btn-primary">
Save
</button>
</div>
</form>
);
}
}
const mapDispatchToProps = (dispatch) => { return { toggleDeleteModal: ()=> { dispatch(toggleDeleteModal()); }, unSelectClub: (row) => { dispatch(unSelectClub(row)) } } };
ClubDetail = connect(null, mapDispatchToProps)(ClubDetail); export default ClubDetail;`
Here is my code for the Input component: `import React, {Component} from 'react';
const Input = ({label, labelPlace, type, error, value, placeholder, onChange, onClick}) => {
var divClassname = "form-group has-feedback";
var labelClassname = "control-label col-md-4 col-sm-4";
var inputClassname = "col-md-8 col-sm-8";
if (labelPlace === 'top') {
divClassname = divClassname + " jumbotron";
labelClassname = "control-label";
inputClassname = ""
}
if (error && (error !== '')) {
console.log(error);
divClassname = divClassname + " has-error";
}
if (value === null) {
value = ''
}
return (
<div className={divClassname}>
<label className={labelClassname} htmlFor="inputSuccess3">{label}</label>
<div className={inputClassname}>
<input
className="form-control"
id="inputSuccess3"
aria-describedby="inputSuccess3Status"
type={type}
value={value}
placeholder={placeholder}
onChange={onChange}
onClick={onClick}
/>
<h5 id="helpBlock2" className="error-message">{error}</h5>
</div>
</div>
);
} export default Input;`
Here is my custom styles:
.clicked-row { td { background: #ab0634; //Red color color: white; // change text color as well position: relative; } } .background{ background: $gray-light; //#EDEDED } .jumbotron { margin: 10px; padding: 8px 15px; background: white; border-radius: 5px; }
The default style I used is bootstrap styles. form-inline is also from bootstrap without any customization.
Thank for the follow up, the library is great! look forward to the new version!
@ZhuQinglei, I've fixed the issues that I mentioned before(on v2.9.0
), you can use options.expanding
to control which row you want to display as expanding, just like selected
, This is a simple example.
For your case, you just only add expanding to your state then you can collapse the row after you clicking save button. If you still doesn't how to implement, please let me know.
BTW, I'm not very professional on CSS, so maybe I cant help you to solve the issue about the save button like broken on UI, But I'll spend some time to reproduce it in my local.
Thanks, Feel free to discuss with me
@AllenFang Thank you so much for the new version! Actually I can close the expansion in old version.
with the function:
const isExpandableRow = (row) => { return (row._id && (_.contains(this.props.selectedClubs, row._id))) };
what I want is to unselect the row on the button click (remove row hight and uncheck checkbox) in addition to row expansion. I check the new version and after I close the expansion the row is still red. Do you have suggestion to solve that?
what I want is to unselect the row on the button click (remove row hight and uncheck checkbox) in addition to row expansion
I thought this is about the state of selection, is that the problem about selected
is not work for you? if true, it was supposed to be work well from very long ago, so could you please make you that your selected
is an row keys array and being updated when you click the save button, if the problem still remain, please let me know, because I've try at my local with a simple example just like I mentioned above, so I guess there're some trouble in your state management(redux), check it out
@AllenFang You are right! It was my redux problem, because I used a non-id column as keyfield and when I update the redux state, I still use array of id for selected row. After I change the keyfield to ids and its working perfect! Thank you so much!
@AllenFang Could you let me know is there a way to set a different trClassName for Expanding rows? By default, the expanding rows are tr and hidden and inherit the same class, please?
@AllenFang Great work, I have a use case for the expanding row, but having trouble getting it to work - have you added to the docs yet?
@nikodonnell, I'll add to docs ASAP and let me know if you got some trouble, thanks. but please open another issue and give more detail or example codes, thanks
I have a customized table implementing with react-bootstrap-table. When I click the row, it expands with red highlight on the row. In the expanded row, I can edit fields and save accordingly. I want to close the expanded row on successful save, and remove the red color highlight. Currently, I can successfully save the record and collapse the expanded row, and here is the code: `class ClubsTable extends Component {
}`
However, I could not figure out how to also unselect the row so that the red color would be removed. I think the isSelected is not updated when I programmatically unselect the the row. And also, when I preselect rows with 'selected: this.props.selectedClubs', the row color will not be updated.
Any ideas?