How to find the id of the active Select2 element - javascript

I have a form with multiple select menus generated with Select2 (version 4) where the id value of each select element is set dynamically. I'd like to find the id of the select element the user clicks on.
I can get this to work
$('.js-example-tokenizer-ajax-data').on('select2:open', function (evt) {
myValue = $(this).attr('id');
});
But I need to use myValue as a parameter for data inside an ajax call so an option getting the id of the active select2 element is needed. I've seen posts that suggest var selectedEle = $(document.activeElement) but I don't know how to get the id from there.
UPDATE
It seems I can include this as the value for the data parameter
data: getSelectedElement(function() {
return JSON.stringify({variable: myValue})
}),
with the function as
function getSelectedElement(callback) {
$('.js-example-tokenizer-ajax-data').on('select2:opening', function (evt) {
myValue = $(this).attr('id');
callback();
});
}
But there are still some timing issues since the ajax seems to fire before a select element is clicked since when I load the page I get an error 'NoneType' object has no attribute '__getitem__' I gather since there was no value for myValue when the page loaded.
Are there other options to get the id of the selected select2 element? Alternatively, are there ways to sort out the timing issue?

If var selectedEle = $(document.activeElement) does in fact get the element that you want you can simply do document.activeElement.id.
Update based on poster's update:
In a different stack overflow answer someone said this.context will give you the correct element, in which case this.context.id would give you the id.

Related

PHP dynamic id attribute of <a> element

I have a drop-down menu in a form with elements retrieved from a database. Something like this :
for($i=0;$i<count($resq);$i++){
print("<li><a class=\"dropdown-item\" href=\"#\" id=\"$i\">{$resq[$i][0]}</a></li>");
}
$resq being an array containing the result of the query (i used mysqli_fetch_all).
As you can see I tried to dynamically generate the id of the items(first item has id=0, second has id=1 and so on till the final value of $i) but I think this is not correct.
Previously, I had the following JS code(which worked) which I used to set the drop-down value to the one selected by the user and to set the value of a hidden input to that value.(I know the code isn't elegant but I just wanted to test the logic in the first place)
var x=document.getElementById('dropdownMenuButton1slct');//dropdown
var c1=document.getElementById("0");//i - categories(IDs of the dropdown elements)
var c2=document.getElementById('1');
var c3=document.getElementById('2');
var c4=document.getElementById('3');
var c5=document.getElementById('4');
var p=document.getElementById('iaval');//hidden input from form
function clic(z){
z.onclick=function () {
x.innerHTML=z.innerHTML;
p.value=x.innerHTML;
};
}
clic(c1);
clic(c2);
clic(c3);
clic(c4);
clic(c5);
But now the same method won't work. If you can, please suggest me a different way or something, I am kinda stuck. I can provide more info if this seems vague or something like that. Thanks.

Get the value of a Combobox select in WP editor

In a Wordpress installation I have a custom post type and a metabox with custom post_meta fields.
Parent dropdown field in Gutenberg's sidebar used to be a <select> element. I have some scripts that onChange trigger the hide/show of different fields making them conditional, depending whether the page being edited is a parent or child:
$(document).on("change", ".editor-page-attributes__parent select", function(){
toggleFields();
}
The options in the <select> have IDs as values so I could get Title and ID for the selected parent and dynamically show some data in the metabox for my user:
var dropdown = $('.editor-page-attributes__parent select');
var parentName = dropdown.find(':selected').text();
var parentId = dropdown.val();
Since v5.6 Wordpress has replaced that select element with a Combo Box. I have tried to get the same data onChange and only had some success using blur:
$(document).on("blur", ".editor-page-attributes__parent .components-combobox-control__input", function(){
toggleFields();
var parentName = dropdown.val();
})
I was only able to get the page title since this combobox now has an input element that's missing IDs, like this one:
<input id="components-form-token-input-0" type="text" class="components-combobox-control__input components-form-token-field__input" value="Page Name Here">
I have also tried doing an Ajax, to retrieve the ID using get_page_by_title() but it does not always work because pages might have the same title and editor also adds dashes and spaces in names for hierarchy levels.
How can I get the associated ID of the page selected in the Parent Combobox on change?
After some time reading the Editor Documentation I found the proper solution. This is how you can listen to changes and get the id of the Parent Combobox select in the WP Editor:
wp.data.subscribe( function () {
var newParent = wp.data.select('core/editor').getEditedPostAttribute('parent');
console.log(newParent);
} );
wp.data.subscribe is called every single time a change occurs in the current state while editing posts in the editor, so the listener function is called every single time. We can avoid that with a simple variable check when there is an actual change to the field we want. It behaves as Redux subscribe without unsubscribe and only one listener.
To also check for the current post type we are editing we can use getCurrentPostType:
wp.data.select('core/editor').getCurrentPostType();
This is the full code for this problem for future reference:
if (wp.data.select('core/editor').getCurrentPostType() == 'cpt_name') {
const getPostParent = () => wp.data.select('core/editor').getEditedPostAttribute('parent');
// set initial parent
let postParent = getPostParent();
wp.data.subscribe(() => {
// get current parent
const newPostParent = getPostParent();
// only if parent changes
if( postParent !== newPostParent ) {
// Do what we want after parent changed
toggleFields();
}
// update the variable
postParent = newPostParent;
});
}

Can't programmatically select option using Select2

I have a Select2 working fine attached to a select list but when someone enters a new item and I rebind the select list and try to programmatically select the new item, it refuses to display.
There are a number of other posts re this but their solutions don't work for me.
Use .select2("val", value). Does nothing.
Use .select2("data", value). Does nothing. Not sure how this is supposed to be different.
Use the InitSelection option to set a value. This leads to the following error message: Uncaught Error: Option 'initSelection' is not allowed for Select2 when attached to a select element.
In the Ajax success function after adding the new option to the database, I have the following Javascript:
BindDishes(RestaurantID); //rebinds the select list successfully
$('#hidDishID').val = data.DishID; //populates a hidden field
var arr = '[{id: "' + data.DishID + '", text: "' + data.DishName + '"}]';
$("#dd").select2("data", arr);
So in this latest iteration I have tried to supply an array with the id and text from the select list item as per another suggested solution but still nothing occurs. What am I doing wrong? Is this impossible when using Select2 with a select list?
Edit: I have the following line in MVC that creates the Select list:
#Html.DropDownGroupListFor(m => m.DishID, Model.GroupedSelectList, "Select a dish", new { id="dd",style="width:470px;" })
which must be causing the problem by binding to DishID from the model which was originally blank when it came from the server. DropDownGroupListFor is just an HTML helper that allows for using OptionGroups in a Select but it must be the binding that is a problem. What is the best approach here, to bind in a different way or to somehow update the model's DishID, not sure of the best practice?
var $example = $(".js-example-programmatic").select2();
$example.val("CA").trigger("change");
You need to destroy your select2 before adding/modifying items. If you do, then your select2 will respond just like its bound first time
Select2 Dropdown Dynamically Add, Remove and Refresh Items from

Using Jquery, load select options on focus

I am trying to load options into a select element when the user focuses.
Here is the jquery code I'm using:
$('select').focus(function() {
var $this = $(this);
if (!$this.data('hasitems')) {
var selectedValue = $this.val();
$this.empty()
.append($('<option></option')
.attr('value','')
.text('Loading...'));
// This would usually be the result of an AJAX call
$this.empty()
.data('hasitems','true');
$.each(['a','b','c','d'], function(index,item) {
$this.append($('<option></option>')
.attr('value',item)
.text(item)
.prop('selected', selectedValue == item));
});
}
});
Here is the fiddle:
http://jsfiddle.net/agnnC/
The solution almost works... except in Firefox (and sometimes not in Chrome either, although the fiddle I put together does appear to work).
The problem in Firefox is that when the user clicks on the select element, the currently selected value is not remembered and is changed to one of the new values in the drop down.
Can anyone think of a workaround?
I think the issue is that the selected attribute is not really a property the way you are using it. Per the MDN doc:
selected
If present, this Boolean attribute indicates that the option is
initially selected. If the element is the descendant of
a element whose multiple attribute is not set, only one single
of this element may have the selected attribute.
Note, it talks about "initially selected" only, not real time changes. It also refers to selected only as an attribute, not a property.
The W3C spec for the option element also talks only about pre-selecting an option, not about making live changes using the selected attribute.
Once the select and options are live, the .selectedIndex property on the <select> object controls which option is selected in real time for single selection select elements.
In support of this theory, if you change to setting the saved item with .selectedIndex as shown below, the problem goes away:
$('select').focus(function() {
var $this = $(this);
if (!$this.data('hasitems')) {
var selectedValue = $this.val();
$this.empty()
.append($('<option></option')
.attr('value','')
.text('Loading...'));
// This would usually be the result of an AJAX call
$this.empty()
.data('hasitems','true');
$.each(['a','b','c','d'], function(index,item) {
$this.append($('<option></option>')
.val(item)
.text(item));
if (selectedValue == item) {
$this.prop("selectedIndex", index);
}
});
}
});
Working demo: http://jsfiddle.net/jfriend00/4333d/
Firefox can't change the focus option when select is opening, but you can change before it open, change the event to mousedown it working Fiddle
$('select').mousedown(function() {
// ...
});

option:selected not triggering .change()

I have a dropdown box that has a list of institutions in it. Now if I manually select an option, it works and I am able to grab the correct value.
However, I have a select rates button which uses JavaScript to pull up a rate sheet. You select a rate from that sheet and it will select an option from the dropdown for you (one that corresponds with the rate from the rate sheet). If I use this method, it doesn't trigger a .change() therefor I can't get a value for the selected option.
$('#id_financial_institution').change(function () {
var value = $("#id_financial_institution option:selected").text()
$("fi").text(value);
});
Any suggestions? I have tried .change() and .click() but nothing.
Once you are in the change function you don't have to do another search or selector because you already have the object you just have to find the selected option from it. So you can try this:
$('#id_financial_institution').change(function () {
var value = $(this).find("option:selected").text();
$("fi").text(value);
});
If the code still doesn't return you answer start to add alerts at each point to see where you are and what values you have and work your way from there?
Rather than .text() use .val()
$(function() {
$('#id_financial_institution').change(function () {
var value = $("#id_financial_institution option:selected").val()
alert(value);
});
})
Here is a sample demo, without your html. I am just alerting the value.
DEMO
You're going about this all wrong. You already have the select element in this, all you need is the value of that select element.
$('#id_financial_institution').change(function () {
var value = $(this).val();
$('#fi').text(value); //i assume `fi` is an [id]
//do more stuff
});
I went inside my AJAX call and got the value of the fields I needed there. For some reason, when using the AJAX call, it wouldn't fire the .change() on that particular field.
Thanks for all your input everyone.

Categories