Reach data-attribute of select2 select - javascript

Is there a way to reach a data-attribute from within a select2?
$('select').select2({
ajax: {
url: url + '&id=' + $(this).attr('data-id')
//...
}
});
//...
<select data-id="1"></select>
<select data-id="2"></select>
<select data-id="3"></select>

To pass a custom param to your ajax url in select2, you should use the data ajax function:
$('select').select2({
ajax: {
url: "zee/base/url" // base url, no params
data: function(params) {
return {
q: params.term, // search term
id: $(this).data('id') // ta daaaa!
page: params.page
};
},
// moar ajax options
},
// moar select2 config options
})
As a general note, this inside select2 config options refers to the select2 instance (which is an object) and this inside the data function outlined above refers to the DOM element select2 was called upon, hence the jQuery wrapper$(this) has a .data() method.

Reading the document, it says that you can insert the url as a data-type in html select tag like so:
<select data-ajax--url="YOUR DESIRED URL" data-ajax--cache="true">
...
</select>
This url will override the options you have set inside of the function when calling, thus using a different one for each option you set it to in html.

Related

How can ajax based Select2 pre-population be formatted?

We've found several examples of pre-populating selected option for Select2, however none of them we could find deal with formatted list and selection options. We have a JS fiddle at https://jsfiddle.net/gpsx62de/26/ that illustrates the issue. In that fiddle, you can type and L or whatever into the select search and the data is returned, the list is formatted, and if you select something, the selection is formatted.
However if you click the button in that JS Fiddle which is intended to simulate pre-population per https://select2.org/programmatic-control/add-select-clear-items#preselecting-options-in-an-remotely-sourced-ajax-select2 the data is returned (you can uncomment the console.log to see it), but the formatted selection shows undefined for the intended values. Does anyone know of a way to get the formatted values for pre-populated data to display correctly?
// Set up the Select2 control
$('#mySelect2').select2({
ajax: {
url: '/api/students'
}
});
// Fetch the preselected item, and add to the control
var studentSelect = $('#mySelect2');
$.ajax({
type: 'GET',
url: '/api/students/s/' + studentId
}).then(function (data) {
// create the option and append to Select2
var option = new Option(data.full_name, data.id, true, true); //**** DOES IT MATTER WHAT IS PASSED HERE BECAUSE WE ARE NOT DISPLAY THE OPTION TEXT?? ***
studentSelect.append(option).trigger('change');
// manually trigger the `select2:select` event
studentSelect.trigger({
type: 'select2:select',
params: {
data: data //**** THIS DOES NOT SEEM TO SUPPORT FORMATTED SELECTIONS, SO HOW CAN THIS BE DONE? ***
}
});
});
The problem is in format_selection function. The format of the object it receives depends on how it was created. When you use new Option(text, value) it receives only the properties of this Option object, not your original object containing all user info.
A workaround is to check of either possible values in the fuction:
function format_selection(obj) {
let name = obj.name || obj.element.text;
let email = obj.email || obj.element.email;
return $(`<div><b>${name}</b></div><div>(${email})</div>`);
}
For this to work you should append the de property on you Option object:
var option = new Option(data.name, data.id, true, true);
option.email = data.email;
$('#sel').append(option).trigger('change');
The problem, in https://jsfiddle.net/gpsx62de/26/ is with the
function format_selection(obj) {
// Just add this to see the obj
console.log(obj);
return $(`<div><b>${obj.text}</b></div><div>(${obj.id})</div>`);
}
The obj object just contains the Option class data, so:
id: "1",
selected: true,
text: "Leanne Graham",
title: ""
So you have to find a way to pass "data.email" to the "format_selection" method
EDIT
This could be a solution
$('#btn').on('click', function() {
$.ajax({
type: 'GET',
url: 'https://jsonplaceholder.typicode.com/users/1'
})
.then(function(data) {
console.log(data)
// create the option and append to Select2
$('#sel').append($('<option />') // Create new <option> element
.val(data.id) // Set value
.text(data.name) // Set textContent
.prop('selected', true)
.attr('data-name', data.name) // Don't know why the .data(key, value) isn't working...
.attr('data-email', data.email))
.trigger('change');
}); //then
}); //click
And
function format_selection(obj) {
return $(`<div><b>${obj.element.dataset.name}</b></div><div>(${obj.element.dataset.email})</div>`);
}
This is the fiddle https://jsfiddle.net/947jngtu/

Use multiselect with dynamically generated select

I am trying to use the multiselect plugin I found on here:
How to use Checkbox inside Select Option
The question above is for a <select> with hard coded <options>.
The <select> I am using generates <options> using jQuery and PHP with this function:
function initializeSelect($select, uri, adapt){
$.getJSON( uri, function( data ) {
$select.empty().append($('<option>'));
$.each(data, function(index, item) {
var model = adapt(item);
var $option = $('<option>');
$option.get(0).selected = model.selected;
$option.attr('value', model.value)
.text(model.text)
.appendTo($select);
});
});
};
initializeSelect($('#salesrep'), 'process/getSalesReps.php', function (item) {
return {
value: item.final_sales_rep,
text: item.final_sales_rep
}
});
I have used the above function several times in different projects, as it successfully creates all of the options brought in by the PHP process. Unless requested, I will not show the code for the process. Just know I am indeed retrieving a group of names and displaying them in the dropdown.
Right beneath the function above is where I call the multiselect feature:
$('select[multiple]').multiselect();
$('#salesrep').multiselect({
columns: 1,
placeholder: 'Select Reps'
});
The HTML for the select is as follows:
<select class="form-control" name="salesrep[]" multiple id="salesrep"></select>
Using all of the above, the output looks like this:
Upon inspecting the element, I can see all of the sales reps names. This tells me that the initializeSelect function is working properly.
Therefore I think the issue must have something to do with the multiselect.
Ajax calls are asynchronous. You call multiselect() before the ajax call has had time to complete and therefore the option list is still empty at the point you call the multiselect() function.
Either move the $('#salesrep').multiselect({.. bit to inside the getJSON method or call the multiselect refresh function after the option list has been populated as I am doing here. (Untested.)
function initializeSelect($select, uri, adapt){
$.getJSON( uri, function( data ) {
$select.empty().append($('<option>'));
$.each(data, function(index, item) {
var model = adapt(item);
var $option = $('<option>');
$option.get(0).selected = model.selected;
$option.attr('value', model.value)
.text(model.text)
.appendTo($select);
});
//now that the ajax has completed you can refresh the multiselect:
$select.multiselect('refresh');
});
};
initializeSelect($('#salesrep'), 'process/getSalesReps.php', function (item) {
return {
value: item.final_sales_rep,
text: item.final_sales_rep
}
});
$('select[multiple]').multiselect();
$('#salesrep').multiselect({
columns: 1,
placeholder: 'Select Reps'
});

Jquery getting new value after data attribute update

I am updating link attribute values via ajax response.but When i am again clicking the button/link getting old values instead of new value.
Below is my codes;
HTML
<div class="calendar-control"><a class="evecal-month-view-control fright next-month" href="#" data-month="2" data-year="2019">Next</a><span class="text-center month-name">January 2019</span><a class="evecal-month-view-control fright prev-month" href="#" data-month="12" data-year="2018">Previous</a></div>
And Jquery code.
jQuery(document).on('click', '.evecal-month-view-control', function(e){
e.preventDefault();
var month = jQuery(this).data('month');
var year = jQuery(this).data('year');
console.log(month);
_getMonthCalendar(month, year);
});
var _getMonthCalendar = function(m, y){
jQuery.ajax({
type: 'POST',
url: eventcaldata.ajaxurl,
data: {
action: 'ec_ajax_month_table',
year: y,
month: m,
nonce: eventcaldata.nonce,
},
beforeSend: function(){
console.log('sending...');
},
success: function(response){
jQuery('.next-month').attr( 'data-month', response.nextmonth.month );
jQuery('.next-month').attr( 'data-year', response.nextmonth.year );
jQuery('.prev-month').attr( 'data-month', response.prevmonth.month);
jQuery('.prev-month').attr( 'data-year', response.prevmonth.year);
}
});
}
First on .next-month class the data-month attribute value is 2
then it is changed to 3 after response.But When i am again clicking
that button i am getting 2 value when it should be 3
The .data() method on jQuery objects caches the value from the initial read. Subsequent call to .data() will first look in jQuery's data storage and send you that value. .attr() won't update the data storage, but will update the attribute in HTML. Use either .data() or .attr() but avoid mix and match.
Do not intermix this usage of attr() and data(). data() caches the value that it reads from the element, and does not update the attribute. So if you update with data, attr will not see it. Pick one or the other, and stick with it.

Isit possible to pass value into <div data-value="" > by jquery?

This is my html code
<div data-percent="" ></div>
This is my javascript
function retrieveProgressbar(){
$.ajax({
type:"post",
url:"retrieveprogressbar.php",
data:"progressbar",
success:function(data){
$(this).data("percent").html(data);
}
});
}
retrieveProgressbar();
I need the value retrieved by ajax to be displayed in the data-percent="". I am not sure how to do that. I have another javascript that needs to use this value to execute.
Need to use .attr() method.
<div data-percent="" id="datadiv"></div>
<script>
function retrieveProgressbar() {
$.ajax({
type: "post",
url: "retrieveprogressbar.php",
data: "progressbar",
success: function (data) {
//$("#datadiv").attr("data-percent", data);
// OR
$(this).attr("data-percent", data);
}
});
}
retrieveProgressbar();
</script>
HTML:
<div data-percent=""></div>
The proper way to assign data on jquery is
var new_data_value = "I will be the new value.";
$("div").data("percent",new_data_value);
The .data() method allows us to attach data of any type to DOM elements in a way that is safe from circular references and therefore from memory leaks.
You can retrieve the data by:
var value = $( "div" ).data( "percent" );
.attr() on the other hand set/get the value of an attribute for the first element in the set of matched elements or set one or more attributes for every matched element.
It does not attach data of any type to DOM elements.
$("div").attr("data-percent",data_value);
Sources:
https://api.jquery.com/data/
http://api.jquery.com/attr/
Yep, you can use the .attr( function instead.
$(this).attr("data-percent", your_value);

Populate items into SELECT with Jquery

I'm having trouble populating a SELECT with jquery, when the user writes the zipcode or part of it, it searches the database and returns this:
{"success":1,"id":"50","street":"Central One"},{"success":1,"id":"60","street":"Central Two"}
One success for each street it finds. For a single street and using a text input I'm using this
UPDATE 1 - FULL CODE
$(document).ready( function() {
$('#zip').blur(function(){
$.ajax({
url : '../../controller/zip.php',
type : 'POST',
data: 'zip=' + $('#zip').val(),
dataType: 'json',
success: function(data){
if(data.sucesso == 1){
$('#id').val(data.id);
$('#street').val(data.street);
}
}
});
return false;
})
});
How can I change this so I can populate a select box.
Thanks
What is being passed back for a single address is a single object from which you can grab the information. When there are multiple responses you need to go through each of them and handle them.
When we look at MDN's article it shows that we need a parent <select> tag and then we need to populate the children. The process would look like this:
Find / create parent select
[Optional] Remove previous child <option> tags
Loop through responses
Create a new <option> element
Populate the <option> with the appropriate value and content
Append it to the parent <select>
Some things to be aware of, if you're clearing the previous addresses each time you get a response from the database you'll want to remove these previous <option>s. This can be done either by .empty() if there are no other children in the parent or starting with the parent <select> and removing all child <options>.
Use this for adding items to select box dynamically:
var $selectBox = $('#selectboxId');
$selectBox.empty();
$.each(data, function (idx, val) {
if (val.success) {
$selectBox.append($('<option>', {
value: val.id,
text: val.street
}));
}
});
I would not encourage to do so; you're better off using a html-templating engine like mustache or handlebars.
Doing this kind of stuff in plain JS (string concatenation) is gross. It pollutes your sourcecode.
Anyways, this would do the trick to generate the necessary HTML:
function generateHTML(data){
return data.reduce(function(o,n){
return o+"<option value='"+n.id+"'>"+n.street+"</option>";
},"");
}
Here is the Fiddle to play with. If you need to filter for success, you could add a filter()
function generateHTML(data){
return data.filter(function(x){
return !!x.success;
}).reduce(function(o,n){
return o+"<option value='"+n.id+"'>"+n.street+"</option>";
},"");
}
You could easily use $("#selectBoxId").html(generateHTML(data)) to insert it to the DOM.
To fit it into your codebase, you should add it in the success handler:
success: function(data){
function generateHTML(data){
return data.reduce(function(o,n){
return o+"<option value='"+n.id+"'>"+n.street+"</option>";
},"");
}
$("select").html(generateHTML(data))
}
For the inner workings of Array.prototype.reduce() take a look at MDN and for Array.prototype.filter()
If the JSON being returned is a list [{...}, ..., {...}], then you can use Array.forEach. Here is the success callback:
function(data) {
data.forEach(function(item) {
if (item.success) {
// use item.id and item.street
}
});
}
If you have a <select> element, then you will want to be populating it with <options>, by appending an <option> element under each successful "if" branch in the forEach.
Assuming you already have the select element on the page and the data that is coming back from the server is an array of objects, this should work:
$.ajax({
url : '../../controller/zip.php',
type : 'POST',
data: 'zip=' + $('#zip').val(),
dataType: 'json',
success: function(data) {
var $items = [];
$.each(data, function(street) {
if(data.success === 1) {
$items.push($('<option />').attr({
value: street.id
}).text(street.street));
}
});
$('#your-select-element').append($items);
}
});
Notice this isn't setting the value for one option, it is creating <option> tags for each of the response's streets and appending them to a <select> element.

Categories