Knockout.js: clear selection in select element - javascript

I need to clear the selection from a <select> element. I've already read such posts as Knockoutjs clear selected value in combobox and have tried the accepted answers, but those solutions don't seem to be working (don't know if something has changed in Knockout 2 since the answer was accepted?).
Here's an example view model:
var ClearSelectionViewModel = function () {
var self = this;
self.station = ko.observable();
self.selectedStation = ko.observable();
self.selectedStation.subscribe(function (value) {
self.station(value);
});
self.stations = ko.observableArray(['CLT', 'PHL', 'PHX', 'PIT']);
self.clearSelectedStation = function () {
self.selectedStation(null);
};
};
ko.applyBindings(new ClearSelectionViewModel());​
When the clearSelectedStation is invoked, the bound view model property should be set to null and this should be reflected in the UI by the bound <select> element appearing blank and expanding the list of options revealing no highlighted items. However, what I'm noticing is that if you try to set the bound value property (selectedStation) to anything not in the array of options (stations), the binding seems to be ignored.
This fiddle illustrates what I'm talking about: http://jsfiddle.net/sellmeadog/Su8Zq/1/
I don't want to "pollute" the options array with a blank value if I don't have to. I would like to know how to get the solution in the linked post to work.

One option would be to use the optionsCaption additional binding for the "not selected" value. It has to be set to something for it to be used, but you could set it to " ".
<select data-bind="optionsCaption: ' ', options: stations, value: selectedStation"></select>
Sample: http://jsfiddle.net/rniemeyer/Su8Zq/3/

Just add an 'optionsCaption', like this:
<select data-bind="options: stations, value: selectedStation, optionsCaption: '-- SELECT --'"></select>
Updated fiddle: http://jsfiddle.net/Su8Zq/2/

Related

How come javascript is recognizing that my control is now holding an array?

I'm working on small MVC application that is "sending emails", and at the begining I used dropdown to choose only 1 receiver, but after that I added multiple class to my dropdownList and when I choose 2-3 receivers and when I tried to debug this code which I used with only one receiver :
$("#SubmitEmail").click(function () {
var Receiver = $('#ReceiverID').val();
var Subject = $('#subject').val();
var Body = $('#content').val();
var obj = { 'Receiver': Receiver, 'Subject': Subject, 'Body': Body };
SendEmail(obj);
});
I realized that var Receiver which I used to store receiverId, become an array acctually, and I'm wondering how come javascript adapted soo cooooool so it recognized that I've selected few items there, and it become an array so I simply looped it (modified my code):
$("#SubmitEmail").click(function () {
var Receivers = $('#ReceiverID').val();
for (var i = 0; i < Receivers.length; i++) {
var Receiver = Receivers[i];
var Subject = $('#subject').val();
var Body = $('#content').val();
var obj = { 'Receiver': Receiver, 'Subject': Subject, 'Body': Body };
}
SendEmail(obj);
});
And everything was cooool, so I'm simply wondering how come js knows it all?
From the jQuery docs on val():
When the first element in the collection is a select-multiple (i.e., a
select element with the multiple attribute set), .val() returns an
array containing the value of each selected option.
So it's actually jQuery magic, not JavaScript magic.
You can see the actual source code for val() here. It's a function that calls the get hook of the select element, which actually does a loop over the selected options.
Javascript is cool as you state, but in this example it, in fact, is a Jquery implementation flexibility which returns array of objects for dropdown. see http://api.jquery.com/val/ for details.
This is how jQuery works. See .val() function:
http://api.jquery.com/val/
Scroll down for this example:
Get the single value from a single select and an array of values from a multiple select and display their values.

Knockout Observable not updating when given a new value

This seems like the most basic part of using knockout, and I'm not sure why it isn't working, but for some reason , 2 of my 5 knockout observables are holding onto their new values.
In the setup of the model:
self.CProviderIdentifier = ko.observable();
self.ReferringProviderIdentifier = ko.observable();
self.BillableCareProviderIdentifier = ko.observable();
self.ServiceLocationIdentifier = ko.observable();
self.PracticeLocationIdentifier = ko.observable();
Inside of an AJAX call which returns a number of items inside of a JSON object, I extract the relevant pieces of information, and put them into the correct observable:
visitModel.CProviderIdentifier(data.CareProviderIdentifier);
visitModel.ReferringProviderIdentifier((data.ReferringProviderIdentifier == null ||
data.ReferringProviderIdentifier == "undefined") ? 0 : data.ReferringProviderIdentifier);
visitModel.BillableCareProviderIdentifier(data.BillableCareProviderIdentifier);
visitModel.PracticeLocationIdentifier(data.PracticeLocationIdentifier);
visitModel.ServiceLocationIdentifier(data.ServiceLocationIdentifier);
Now, if none of them worked, it would make (some) sense, but only CProviderIdentifier and ReferringProviderIdentifier have no data. I've checked the data in a break point right before getting into setting the properties, and the values from data are 1003 and 0, but the two observables are undefined are the above block of code.
I'm working on getting a fiddle working for this: https://jsfiddle.net/bz3mq6z9/
The assignment is made in the loadData function. Inside it, Javascript does not know what is visitModel. That variable does not exist and does not have any purpose in the setter.
Use self instead of visitModel. That way knockout knows that he is assigning values to the view model
Greetings
You have some bugs in your code:
should bind viewmode with DOM using:
ko.applyBindings(visitModel);
ko.observable is a function, so you should use call it before combine string.
<span data-bind="text: CProviderIdentifier() + 'cp'"></span>
it's not a good idea use visitModel in LoadData function, you can just use self to keep the reference.
see this demo: http://jsfiddle.net/bz3mq6z9/6/

Delaying select2 opening to fill it with data

I have a dropdown which I'm filling data by calling a function list(), which makes json calls and filters necessary data according to different parameters (It's very complex, and I'm not using the built in ajax feature).
Here's my code:
$("select.mission:visible").on("select2-opening", function() { list(); });
It works flawlessly, except for one little problem - updating the list is done while opening so the updated list doesn't show when you first open the dropdown. On the second open it shows the correct options.
I considered using select2-focus, but it's called twice, in the beginning and in the end. The second call repopulates the list and while the selected option is still highlighted, the value passes down as undefined.
The solution I look for is delaying the opening of the list to let it populate.
Any ideas in this direction or another?
it is a bit late for this question. I have the similar problem as you and I have solve it as below:
$("select.mission:visible").on("select2-open", function() {
$.getJSON("path-to-json", function(data) {
var results_data = [];
$.each(data.feed.entry, function(i, entry) {
results_data.push({'id':entry.id, 'text':entry.text})
});
// if your element select.mission:visible is select convert it to input:hidden
var id = $(this).attr('id') // get old id
var name = $(this).attr('name') // get old name
var oldVal = $(this).val() // get old value
$('select.missions').empty(); // empty select options
$(this).select2('distroy') // destroy current select2 obj
$(this).replaceWith(`<input type='hidden' class='mission' id='${id}' name='${name}'>`) // convert select element to input element
$(this).val(oldVal) // set new input element to previous value
$(this).select2({data:results_data}) // set new option items to new input element select2
$(this).select2('open') // force select2 element to open dropdown
});
});
Because I don't know which version of select2 you're using, but from your code, I assumed you are using select2 version 3.x. For more detail check it at https://select2.github.io/select2/

Knockout js: Viewmodel property not being bound

This is my fiddle. http://jsfiddle.net/aaScC/
Please check in the example, the Score property has 3.5 value but it is being displayed as 1. I know the score property is bound to dropdown value so its coming as 1. But i want 3.5 to be displayed. Please help.
var GoalsModel = function (goals) {
var self = this;
self.goals = ko.observableArray(ko.utils.arrayMap(goals, function (goal) { return new Goal(goal) }));
};
The problem is that you just make the select element invisible. You don't want the element at all. You can use bindings if or ifnot to control this.
Here is an updated example: http://jsfiddle.net/waxwing/aaScC/1/ . I wrapped the select inside a span to make it work, but you can also use virtual bindings if you don't like to change your DOM structure.

Why am I getting "undefined" when I call .options on my select box?

I am trying to follow this tutorial (http://railscasts.com/episodes/88-dynamic-select-menus) to get dynamic select boxes working with RoR. No need to worry about the RoR bit, this is a Javascript specific question.
Every time this function runs I get the error that the "options" is undefined. I've tried running the command manually in the console, but regardless, it spits out undefined. I have it typed exactly as I see it in the tutorial, but somehow it's not working for me...
Here's the javascript in question:
function clientSelected() {
var client_id = $('#piece_client_id').val();
// THIS IS THE PROBLEM LINE
var options = $('piece_campaign_id').options;
options.length = 0;
campaigns.each(function(campaign) {
if (campaign[0] == client_id) {
options[options.length] = new Option(campaign[1], campaign[2]);
}
});
if (options.length == 1) {
$('campaign_field').hide();
} else {
$('campaign_field').show();
}
}
Here is the HTML that it's trying to work on:
<select id="piece_campaign_id" name="piece[campaign_id]"><option value=""></option>
<option value="1">Feed The Dogs</option>
<option value="2">Watch Television</option>
<option value="3">End The Suffering</option>
<option value="4">Brian Bilbrey</option>
<option value="5">SummerHill Homes / Yes on A&B</option>
</select>
Thanks a bunch for taking a look! Let me know if there's anything else I can add to make my question more clear.
Try:
var options = $('#piece_campaign_id').get(0).options;
or
var options = $('#piece_campaign_id')[0].options;
As you were using a jQuery object, which doesn't have an options property. Also, make sure to include the id selector (#).
The following code in is not accurate.
var options = $('piece_campaign_id').options;
Should be
var options = $('#piece_campaign_id')[0].options;
You will notice two changes.
The addition of the # in the selector
The addition of the [0] after the jQuery object.
In jQuery to select an element by an ID you need to append # before the idvalue (which is similar to CSS. Here is some reference http://api.jquery.com/id-selector/
The next issue was you were trying to access a property that does not exist on a jQuery object. options is an HTML DOM property. Because of this you must access the DOM Object from inside the jQuery Object.
var options = $('#piece_campaign_id') //Returns jQuery Object
var options = $('#piece_campaign_id')[0] //Returns HTML DOM Object
//The line above will return the same as
var options = document.getElementById('piece_campaign_id')
NOTE
The following Selectors in your code are most likely inaccurate
$('campaign_field').hide();
...
$('campaign_field').show();
$('piece_campaign_id')
needs to be
$('#piece_campaign_id')

Categories

Resources