Reputation: 69
As that title says, I am attempting to use the same javascript function multiple times on the same page. Basically, I have 2 separate drop downs that call users via ajax so that even new users will be present. (The site is based off not having to always reload.) Anyways, the way I currently have it setup is something like this...
Javascript:
function getAllUsers() {
(function getAllUsers() {
$.ajax({
url: 'staff/getAllUsers.php',
success: function(data) {
$('#getAllUsers').html(data);
},
complete: function() {
// Schedule the next request when the current one's complete
setTimeout(getAllUsers, 5000);
}
});
})();
}
getAllUsers();
function getAllUsers2() {
(function getAllUsers2() {
$.ajax({
url: 'staff/getAllUsers.php',
success: function(data) {
$('#getAllUsers2').html(data);
},
complete: function() {
// Schedule the next request when the current one's complete
setTimeout(getAllUsers2, 5000);
}
});
})();
}
getAllUsers2();
I am sure that doing it like this is unpractical, hence why I am asking for some guidance now.
This is the current HTML setup for it on the dropdowns:
<select class="select2" name="user" id="getAllUsers" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
<select class="select2" name="user" id="getAllUsers2" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
Obviously the Loading Users... option is replaced when the ajax data is loaded.
Again though, I am sure that a better way of doing this exists.
But whenever I try to do something like this with the html... using the same javascript function, the second one just stays at "Loading Users..."
<select class="select2" name="user" id="getAllUsers" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
<select class="select2" name="user" id="getAllUsers" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
I would think that doing it the way I currently do with multiple functions all calling the PHP file constantly can cause load time issues after a while espically if I add more.
Thank you for any assistance!
Upvotes: 3
Views: 470
Reputation: 10361
First, you need to understand why it doesn't work for you and then find a solution.
The problem is that, you are using the same element ID in two separate elements, this is not strictly forbidden and will not throw you any errors, but it points to a wrong implementation.
When you are trying to select elements with the ID getAllUsers
using jQuery, it knows that there should be only one such element, so it selects only the first one. Any other elements with the same ID are ignored. That's why it worked only for the first one.
Now, let's try to find solutions.
One solution, as Miroslav Glamuzina suggested is correct and works, but not flexible enough.
Another solution would be using a selector that selects multiple element which is not an ID. The best option is to use element's class, that will be unique for your two (or more) select
elements. So if you want to add another one in the future, you don't have to touch the JS code, but only the HTML part.
You can do something like this:
HTML
<select class="select2 getAllUsers" name="user" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
<select class="select2 getAllUsers" name="user2" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
(Note that I also changed the name
attribute of the second select
, to prevent issues in the future)
JavaScript
(function getAllUsers() {
$.ajax({
url: 'staff/getAllUsers.php',
success: function(data) {
$('.getAllUsers').html(data);
},
complete: function() {
// Schedule the next request when the current one's complete
setTimeout(getAllUsers, 5000);
}
});
}());
WARNING!
If you are planning to use this script publicly, you should pay attention on the security issue in this script.
This script is opened for XSS attacks. Because, you are requesting a remote content and applying its content as HTML without any data validations nor escaping.
I would suggest in your case, to generate a JSON in the PHP script, with the list of users and all the data you need, then on the JavaScript, create option
elements using the data from the JSON list.
You should do something like this:
Let's say that this is the JSON received from staff/getAllUsers.php
:
[
{"id": 14, "name": "User 1"},
{"id": 16, "name": "User 2"},
{"id": 17, "name": "User 3"}
]
JavaScript:
(function getAllUsers() {
$.ajax({
url: 'staff/getAllUsers.php',
success: function(data) {
try {
const list = JSON.parse(data); // Parse JSON from string to object
const selectEl = $('.getAllUsers').empty(); // Clear the content of both `select` elements
for ( let i=0; i<list.length; i++ ) { // Loop through each item in the JSON array
$('<option />') // Create an `option` element
.attr('value', list[i].id) // Set attribute `value` to `option` element
.text(list[i].name) // Set `option` text (this function also escapes any special characters, which prevents potential XSS attacks)
.appendTo(selectEl); // Add `option` element to both `select` elements
}
} catch (e) {
// Report any errors with the JSON parsing process to the developer console.
console.error(e);
}
},
error: function(jqXHR, textStatus, errorThrown) {
// Track any errors received from the server for debugging purposes
console.error(textStatus, errorThrown);
}
complete: function() {
// Schedule the next request when the current one's complete
setTimeout(getAllUsers, 5000);
},
dataType: 'json' // Expect a `json` back from server
});
}());
I hope you can learn something from this.
Good luck!
Upvotes: 1
Reputation: 4557
Both select2
's are using the same endpoint, why not just assign the value in the same ajax request?
Something like this will be okay:
function getAllUsers() {
$.ajax({
url: 'staff/getAllUsers.php',
success: data => {
$('#getAllUsers').html(data);
$('#getAllUsers2').html(data);
},
error: err => {
//$('#getAllUsers').html("<option>test</option>");
//$('#getAllUsers2').html("<option>test</option>");
},
complete: () => {
// Schedule the next request when the current one's complete
setTimeout(getAllUsers, 5000);
}
});
}
getAllUsers();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="select2" name="user" id="getAllUsers" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
<select class="select2" name="user" id="getAllUsers2" required>
<option selected="true" disabled="disabled">Loading Users...</option>
</select>
Upvotes: 3