'How to set attributes to the other items in array besides the selected element (this)?
I would like to make buttons in my HTML while one of my JS classes is running and receives a response from the backend. I'm using jQuery and vanilla JS and created an example below. In this example, I'd like to dynamically disable the button that was not clicked to show the user that something is happening and that they should not click elsewhere until a response is returned.
Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
button.addEventListener("click",
function(){
let buttonSpinner = this.getElementsByTagName("span")[0];
buttonSpinner.classList.remove("d-none");
// here I would like to disable the button that wasn't selected
let destination = this.value;
uploadData(destination, buttonSpinner);
}
)
})
function uploadData(destination, buttonSpinner){
let link = "https://www.google.com/";
let description = "Stack Overflow";
new Upload(link, description, destination, buttonSpinner)
}
class Upload {
constructor(link=null, description=null, destination="submit", buttonSpinner=null){
this.link = link;
this.description = description;
this.destination = destination;
this.buttonSpinner = buttonSpinner;
this.log();
this.disableButtonSpinner();
}
log(){
console.log(this.link)
}
wait(){
return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
}
async disableButtonSpinner(){
await this.wait() // simulate backend returning data
this.buttonSpinner.classList.add("d-none");
}
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div>
<button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
Upload & View My Data
<span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</button>
<button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
Upload & Submit
<span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</button>
</div>
Solution 1:[1]
You can add a parameter in the function to access the click event I used e. Then You can loop through your buttons and disable other than events target. This is achieved by Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => { if(e.target !== insideButton) insideButton.disabled = true});
Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
button.addEventListener("click",
function(e){
let buttonSpinner = this.getElementsByTagName("span")[0];
buttonSpinner.classList.remove("d-none");
// here I would like to disable the button that wasn't selected
Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
if(e.target !== insideButton)
insideButton.disabled = true});
let destination = this.value;
uploadData(destination, buttonSpinner);
}
)
})
function uploadData(destination, buttonSpinner){
let link = "https://www.google.com/";
let description = "Stack Overflow";
new Upload(link, description, destination, buttonSpinner)
}
class Upload {
constructor(link=null, description=null, destination="submit", buttonSpinner=null){
this.link = link;
this.description = description;
this.destination = destination;
this.buttonSpinner = buttonSpinner;
this.log();
this.disableButtonSpinner();
}
log(){
console.log(this.link)
}
wait(){
return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
}
async disableButtonSpinner(){
await this.wait() // simulate backend returning data
this.buttonSpinner.classList.add("d-none");
}
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div>
<button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
Upload & View My Data
<span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</button>
<button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
Upload & Submit
<span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</button>
</div>
Solution 2:[2]
adding this solution to fix the issue with @Raven solution where the buttons remain disables even after the operation is done.
Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
button.addEventListener("click",
async function(e){
let buttonSpinner = this.getElementsByTagName("span")[0];
buttonSpinner.classList.remove("d-none");
// here I would like to disable the button that wasn't selected
Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
if(e.target !== insideButton)
insideButton.disabled = true}
);
let destination = this.value;
await uploadData(destination, buttonSpinner);
}
)
})
async function uploadData(destination, buttonSpinner){
let link = "https://www.google.com/";
let description = "Stack Overflow";
await new Upload(link, description, destination, buttonSpinner)
}
class Upload {
constructor(link=null, description=null, destination="submit", buttonSpinner=null){
this.link = link;
this.description = description;
this.destination = destination;
this.buttonSpinner = buttonSpinner;
this.log();
this.disableButtonSpinner();
}
log(){
console.log(this.link)
}
wait(){
return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
}
async disableButtonSpinner(){
await this.wait().then(()=>{
Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
insideButton.disabled = false;
}
);
}) // simulate backend returning data
this.buttonSpinner.classList.add("d-none");
}
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<div>
<button class="btn btn-primary upload-button" id="upload-user-data-button" value="data">
Upload & View My Data
<span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</button>
<button class="btn btn-primary upload-button" id="upload-submit-button" value="submit">
Upload & Submit
<span class="ms-2 spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
<span class="visually-hidden">Loading...</span>
</button>
</div>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Raven |
| Solution 2 | shubham patil |
