I have a jQuery UI select widget.
Widget may be fully re-initialized after Ajax call that returns html of select, on which afterwords widget is applied.
The problem is that after widget initialization the actual chosen select option is not selected.
When debugging I'm getting following outputs from Chrome DevTools console:
> thisWidget.element
[<select name="main.model" id="ui-id-297" style="display: none;"><option selected="selected" value> Choose </option><option value="express"> Express </option></select>]
> thisWidget.element.find('option')
[<option selected="selected" value> Choose </option>, <option value="express"> Express </option>]
> thisWidget.element.find('option:selected')
[]
> thisWidget.element.find("option[value='']")
[<option selected="selected" value> Choose </option>]
> thisWidget.element.find("option[value='']:selected")
[]
As I see it the html on which widget is initialized is correct, but the option with empty value is not selected despite that it should be.
Why am I getting this behavior ?
I found out why.
I was setting select value before widget was destroyed and re-initialized.
So events were occuring like this:
// getting re-rendered html select through ajax call
mySelect.val('foo') // setting the value of select which in fact may not have option with such value
// ...then destroy event occurs
// ... and then widget is reinitiazlied
So probably interlieving with undestroyed widget and value setting (mySelect.val('foo')) was the cause of such behavior.
Related
so I have a select box like this with more elements being loaded in of course.
<select class="cherry-dropdown">
<option class="cherryOption" value="#cherry_'.$rownum.'">'.$name.'</option>
</select>
And. I'm trying to use javascript to take me to the appropriate page location based off the value attribute in the option.
$('.cherry-dropdown').click(function(){
console.log("yes");
$('.cherryOption').click(function(){
console.log("maybe");
window.location=$(this).val();
});
});
I'm getting yes from the first console.log (opening the select box to reveal the options). But when I click an option I'm not getting the maybe console.log, and thus the window.location part isn't working as well.
What am I doing wrong here...
You only actually need one event listener here, if you target the select menu itself (.cherry-dropdown) and listen for a change event instead of click, and then by passing the event as a argument to access it's value.
$(".cherry-dropdown").change(function (e) {
console.log(e.target.value); //Returns the selected options value
window.location = $(this).val();
});
I'm using a combination of JQuery EasyUI and Select2 to be able to drag options from a right panel, onto a left select box.
In the original HTML, the select boxes are empty, and I only "add" anything to them if I drop an option on them,
<form id="section1">
<select class="select2" class="drop_target" id="selected_options" name="selected_options"></select>
<div>
<div class="draggable_option" data-id="1234">1234</div>
</div>
</form>
<form id="section2">
<select class="select2" class="drop_target"></select>
<div>
<div class="draggable_option" data-id="1235" id="selected_options" name="selected_options">1235</div>
</div>
</form>
Then in javascript, I do something like this,
$('.drop_target').droppable({
accept: '.draggable_option',
onDrop:function(e, source){
var $dragged_source = $(source);
var $drop_target = $(this);
}
});
The problem comes at this point, if you're dynamically adding things to the select, you have to check it doesn't exist, and if it doesn't, you create a new option, and add it,
var new_option = {
id: $drag_source.data('id'), data_id: $drag_source.data('id'),
text: $drag_source.val(), selected: true};
// Set the value, creating a new option if necessary
if (!$drop_target.find("option[value='" + new_option.id + "']").length) {
// Append it to the select
$drop_target.append(new Option(
new_option.text, new_option.id, true, true)).trigger('change');
}
var data = $drop_target.select2('data');
$drop_target.select2('data', data.concat([new_option]));
Clear as mud? Unfortunately it goes wrong at this point. While all calls to .select2 from $drop_target work as expected, this is not the select that was originally in the HTML, this is a div that select2 created, after hiding the original select, with an id attribute like id="s2id_selected_options". So when we append the new option to it, it doesn't get added to the select, and gets added to select2's div incorrectly instead.
My HTML pseudocode is deliberately set up in this "obtuse" way, because my page is like that. I have multiple forms, and multiple "identical" selects in those forms, generated by WTForms. So the "general" method of selecting your select by id, $('#selected_options') doesn't work correctly.
What I need to do, within the javascript, is gain access directly to the original, now hidden, select, and I can't access it via id.
When you have access to one of the elements that's "associated" with the generated by select2, you can access meta information for it via .data('select2'), or in this instance,
$(this).data('select2');
In here, there's loads of metadata that select2 uses (which you can see if you browse the source). For this question, to get the original select or input element, you can use,
var $drop_target = $(this).data('select2').opts.element;
Whether you're using a select, or an input, this gives you a jQuery element linking to it. If you're using a select, and are only interested in that, you can use the shorter option,
var $drop_target = $(this).data('select2').select;
This may be in the docs somewhere, but I was unable to find it, and I'm also not able to find it by searching now, because searching the docs for "data" and "select2" returns a result for nearly every page of their docs (hence the reason I'm answering this question myself, to hopefully save others the trouble).
I have a cascading dropdown using VueJS (1.0), and I'm having a problem where a change in the Vue model isn't being reflected in the DOM.
The elements in the dropdown need to be an object, but once selected I'm trying to change the value of the property/dropdown to an int.
I'm doing this with a watch event, which processes the necessary information from the object, then uses $set on the property to set it to the required int.
Using the VueJS Chrome dev tools, I can see the change reflected on the component's property, but when submitting the form it's POSTed as the string [object Object], as if the DOM was never updated.
Here is the relevant dropdown in the template:
<select :disabled="releases.length < 1" v-model="release" options="releases" class="form-control input-sm" name="{{formname}}[release_id]">
<option selected="selected" value="">Choose Release...</option>
<option v-for="obj in releases" v-bind:value="obj">{{obj.text}}</option>
</select>
And here is the watch event:
"release": function() {
this.$parent.$data.promos = this.release.promos;
this.$set('release', this.release.id);
}
After changing the dropdown, the root promos property is updated, and according to dev tools the release property of the component is correctly set to the id
But when the form is submitted, I just get the string representation of the object!
Does anyone know what I'm doing wrong here; or is this a VueJS bug/is there a workaround?
Thank you!
I will not be able to find the bug in your code unless I can play around with it in jsFiddle or equivalent.
But I have an alternate implementation of cascading dropdown for you here: https://jsfiddle.net/mani04/Lgxrcc5p/1/
You may see if that provides any pointers. This example uses Vue 2.0.3
In your code sample above, I specifically do not understand this part:
<select :disabled="releases.length < 1" ...
Is that a copy-paste error? I hope you have the following code in your editor:
<select :disabled="releases.length < 1" ...
The value attribute of an option can be tied to an object in Vue, but the browser still needs to render the value as valid HTML so the object is cast to a string.
One thing you can do is add a hidden field to the form with a value set to the ID of the selected release object.
Edit: Another option could be overriding the toString method of the class prototype to return the ID of the object.
function GenericSelectFirst(e){
// This function is called without any errors, I have verified it
e.sender.select(0);
}
<select class="full-width"
name="..."
data-bind="source: ..., value: ..., visible: ..., events:{dataBound: Function.GenericSelectFirst}"
data-role="dropdownlist"
data-value-field="..."
data-text-field="..."
data-value-primitive="true"
data-auto-bind="true"
required="required"
>
</select>
I did not think that it is that hard to achieve such a common easy scenario, but I have a Kendo DropDownList which initialize using MVVM style, and it is binding a remote datasource.
What I want to achieve is that, once the remote datasource is ready and bound to the widget, the first option is selected by default (and of course the value of the first item should be bound to the view model)
I tried to do it directly with the above code, which binds an dataBound event to the widget, and select the first item when it fires. The callback method has been called without errors, but the widget never select the first option but keep selecting the first default "empty" option.
What did I do wrong and how can I fix it? Any advice is appreciated!
Wich Kendo version are you using? If latest, remember that since
V. Q1 2015 , In order to match the Html Select behavior better and solve some issues related to MVVM value binding, the dropdownlist now allows to clear its value (deselect the selected item). This will introduce the following breaking changes:
The widget will not select the first item, when its selected index is -1
The widget will not select the first item, when the selected value is not present in the data source.
Long story short, If someone wants to get the previous behavior, then he/she will need to select first item manually:
dataBound: function() {
if (this.select() === -1) { //check whether any item is selected
this.select(0);
this.trigger("change");
}
}
I'm trying to use JavaScript to change properties or attributes of an ASP.NET ListBox's options, but the only changes that the server sees on postback (asp:Button click) are the selected state of the options. I'm ultimately trying to convey that the SS code should ignore certain selected options, and I was hoping I could use something simple like noting its hidden state, setting the option's disabled property, or adding an attribute. The control, and some failed JS lines:
<asp:ListBox ID="lstFacilities" runat="server" SelectionMode="Multiple" Height="200" />
//lbxFacs returned by document.getElementById
lbxFacs.options[f].style.display = 'none';
lbxFacs.options[f].disabled = true;
lbxFacs.options[f].setAttribute('disabled', 'disabled');
I hide them from view after selecting a filter from another control, and that works from the UI standpoint, but the server seems to have no way of knowing they're hidden. I try to disable them, but the Enabled property is always true. Adding attributes is useless too; the Attributes collection is always empty. Server-side snippet:
bool allSelected = lstFacilities.Items[0].Selected; //"All Facilities", only want visible options
foreach (ListItem option in lstFacilities.Items)
{
var optAtts = option.Attributes; //Always empty
if ((allSelected || option.Selected) && option.Value != "All" && option.Enabled)
selectedFacsIDs += "," + facID; //Always gets here when only "All" selected and some options invisible
}
I can't even get changes to the options' text or values to come in SS. I've also tried the jQuery equivalents. Is there any way to rectify this, or will I have to invoke my proven backup plan of having the JS set the value of a hidden input for the server to read which options are valid? Thanks...