I have searched everywhere for this, yet every example seems to not match what I want. Once a button has been clicked, for a particular table row, I need to disable that current row, or even better disable the button on the row.
The code I have previously written just disables the buttons for every row. Which would not be correct. For some context, see the screenshot of the app im writing:
When the user clicks Generate Journey for a particular row, I need to disable the 'Generate Journey' button for that particular row, to stop them from doing it again (Which will cause issues server side).
I'm guessing to someone who is experienced in React, this is an easy task, but ive tried different things and each one does not give me the result I want.
So here's my code:
The render function of the screenshot above is as follows:
render() {
return (
<div className="polls-container">
<div className="dashboard-title" style={{paddingTop: "2%", marginLeft: "-50px"}}>
<h2>Dashboard</h2>
</div>
{
!this.state.loading && this.state.results.length > 0 ? (
<RouteTable buttonDisabled ={this.state.emulateButtonDisabled} results={this.state.results} generateJourney={this.generateJourney} startEmulation={this.getJourneyEmulations}/>
) : null
}
{
!this.state.isLoading && this.state.results.length === 0 ? (
<div className="no-polls-found">
<span>No Active Journey Generations</span>
</div>
): null
}
{
this.state.isLoading ?
<LoadingIndicator />: null
}
</div>
);
}
}
This basically calls off to the Route Table component, which renders the table seen in the screenshot. Notice how I pass results={this.state.results} generateJourney={this.generateJourney} startEmulation={this.getJourneyEmulations} down as props.
The results prop is just basically the fetched table data. The code for the 'generateJourney' function is as follows (Executed when Generate Journey button is clicked):
generateJourney = (customerId, startDate, endDate, linkedCustomers, lat, lng) => {
let confirmGenerateJourney = window.confirm('Are you sure you want to start this Journey Generation?')
if (confirmGenerateJourney) {
fetch('http://10.10.52.149:8081/generate-journeys', {
method: 'POST',
mode:'cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify( {
customerId: customerId,
startDate: startDate,
endDate: endDate,
serviceIds: linkedCustomers,
homeLat: lat,
homeLng: lng
})
}).then(response => response.json())
.catch(err => console.log(err))
notification.success({
message: 'Kinesis Fake Telemetry',
description: "Journey has Started being Generated",
});
fetch('http://localhost:8080/api/routeGen/updateCustomerStatus', {
method: 'PUT',
mode:'cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify( {
customerId: customerId,
status: 1
})
}).then(response => response.json())
.catch(err => console.log(err))
window.location.reload();
}
}
Nothing fancy, just simply calling off to API's to POST or PUT data. Following this, here is the code for the startEmulation={this.getJourneyEmulations} which is clicked when the Emulate button is clicked. This basically checks that the journey has been generated before we can emulate it. (Waits for a status of finished)
My RouteTable class is then as follows:
export class RouteTable extends Component {
constructor(props) {
super(props);
}
getStatus(result) {
let status;
if (result.customerStatus === 0) {
status = (<Badge color={'secondary'}> Pre Journey Generation</Badge>)
} else if(result.customerStatus === 1) {
status = (<Badge color={'success'}> In Journey Generation</Badge>)
} else if (result.customerStatus === 2) {
status = (<Badge color={'info'}> Ready for Emulation</Badge>)
} else {
status = (<Badge href="/journeyEmulation" color={'danger'}> In Emulation</Badge>)
}
return status;
}
render() {
const {startEmulation, buttonDisabled} = this.props;
const items = this.props.results.map(result => {
const serviceIdList = [];
const deviceRequests = [];
result.linkedCustomers.map(x => { const emulationData = {"imei": x.imei, "serviceId": x.serviceId, "deviceType": "CALAMP"}
deviceRequests.push(emulationData)
});
result.linkedCustomers.map(x => {serviceIdList.push(x.serviceId);});
return (
<tr key={result.linkedCustomerId}>
<th scope="row">{result.customerName}</th>
<td>{result.linkedCustomerId}</td>
<td>{result.numDevices}</td>
<td>{result.startDate}</td>
<td>{result.endDate}</td>
<td>{result.lat}</td>
<td>{result.lng}</td>
<td> {this.getStatus(result)}</td>
<td>
<div style={{width:"100%"}}>
<Button style={{width: "50%"}} color="primary" onClick={() => this.props.generateJourney(result.linkedCustomerId, result.startDate, result.endDate, serviceIdList, result.lat, result.lng)} disabled={buttonDisabled}>Generate Journey</Button>
{' '}
<Button style={{width: "50%", marginTop: "4%"}} color="danger" onClick={() => startEmulation(result.linkedCustomerId, result.customerName, result.startDate, result.endDate, deviceRequests)}>Emulate Journey</Button>
</div>
</td>
</tr>
)
})
return (
<div className="tableDesign" style={{marginTop: "2%"}}>
<Table hover>
<thead>
<tr>
<th>Customer Name</th>
<th>Kinesis Customer Id</th>
<th>Number of Devices</th>
<th>Start Date</th>
<th>End Date</th>
<th>Home Lat</th>
<th>Home Long</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{items}
</tbody>
</Table>
</div>
)
}
Now my problem is how do I disable the user from generating the journey twice? I have tried the solution posted which just disables all buttons for every row. Any help would be massively appreciated as this is becoming frustrating!! Im guessing I can somehow use the row key of the table
<tr key {result.linkedCustomerId}> to target the specific button to disable?
Thanks for your help :)
***** EDIT *****
generateJourney = (customerId, startDate, endDate, linkedCustomers, lat, lng) => {
let confirmGenerateJourney = window.confirm('Are you sure you want to start this Journey Generation?')
if (confirmGenerateJourney) {
this.setState({generatingId: customerId});
fetch('http://10.10.52.149:8080/generate-journeys', {
method: 'POST',
mode:'cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify( {
customerId: customerId,
startDate: startDate,
endDate: endDate,
serviceIds: linkedCustomers,
homeLat: lat,
homeLng: lng
})
}).then(response => {
this.setState({generatingId: null});
// response.json();
}).catch(err => {
this.setState({generatingId: null});
console.log(err)
})
notification.success({
message: 'Kinesis Fake Telemetry',
description: "Journey has Started being Generated",
});
fetch('http://localhost:8080/api/routeGen/updateCustomerStatus', {
method: 'PUT',
mode:'cors',
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify( {
customerId: customerId,
status: 1
})
}).then(response => response.json())
.catch(err => console.log(err))
// window.location.reload();
}
}
Props passed down to RouteTable
{
!this.state.loading && this.state.results.length > 0 ? (
<RouteTable generatingId ={this.state.generatingId} results={this.state.results} generateJourney={this.generateJourney} startEmulation={this.getJourneyEmulations}/>
) : null
}
Then in RouteTable:
<Button style={{width: "50%"}} color="primary" onClick={() => this.props.generateJourney(result.linkedCustomerId, result.startDate, result.endDate, serviceIdList, result.lat, result.lng)} disabled={this.props.generatingId === result.linkedCustomerId}>Generate Journey</Button>

buttonDisabledprop to true, does it disable the button? Just wanna make sure it isn't an issue with the button component you are tryna disable.