the problem is in the asynchronous nature of JavaScript the app is not waiting for the response of the blockchain before removing the old so what happens is that the data get inserted to the dom two times, the fix is to handle the promises differently. Group all the promise calls to get candidates to an array, then waiting until all of them are resolved to add them to the dom.
App.contracts.Election.deployed()
.then(function(instance) {
electionInstance = instance;
return electionInstance.candidatesCount();
})
.then(function(candidatesCount) {
const promises = [];
// Store all prosed to get candidate info
for (var i = 1; i <= candidatesCount; i++) {
promises.push(electionInstance.candidates(i));
}
// Once all candidates are received, add to dom
Promise.all(promises).then(candidates => {
var candidatesResults = $("#candidatesResults");
candidatesResults.empty();
var candidatesSelect = $("#candidatesSelect");
candidatesSelect.empty();
candidates.forEach(candidate => {
var id = candidate[0];
var name = candidate[1];
var voteCount = candidate[2];
// Render candidate Result
var candidateTemplate =
"<tr><th>" +
id +
"</th><td>" +
name +
"</td><td>" +
voteCount +
"</td></tr>";
candidatesResults.append(candidateTemplate);
// Render candidate ballot option
var candidateOption =
"<option value='" + id + "' >" + name + "</ option>";
candidatesSelect.append(candidateOption);
});
});
return electionInstance.voters(App.account);
})