Update field with jquery don't update observable - javascript

I want to say hello to the stackoverflow community.
I've just started using knockout a few days ago.
Right know I'm using it to make a dynamic menu builder for a CMS I'm working on.
Here is the code: http://jsfiddle.net/dnlgmzddr/HcRqn/
The problem is that when I choose an element from the select box, the input field update as I expect, but the observable doesn't reflect the change. Because of that, the add button is not enabled.
What am I missing? How can I fix it?
Thank you.

When you populate the url field, you would need to trigger the change event to get the observable to be upated. So, you could do:
$("#url").val('/pages/' + id).change();
Another option though that is more in the Knockout spirit is to use a binding on your select. In this case, you would likely want to populate an observable with that value, then use a manual subscription to default the formatted value into the input field.
this.itemUrl = ko.observable();
this.selectedUrl = ko.observable();
this.selectedUrl.subscribe(function(newValue) {
if (newValue) {
this.itemUrl("/pages/" + newValue);
}
}, this);
Then, bind your select to selectedUrl:
<select id="pagedList" data-bind="value: selectedUrl">
<option value=""><option>
<option value="test">Test</option>
</select>
Here is a sample: http://jsfiddle.net/rniemeyer/HcRqn/21/
You could also eliminate the extra observable and manual subscription if the "value" of your options was the url.

I can't see anywhere in your code where you are actually enabling the button when a field is selected. So I might be missing something, but just enable the button on change. Like the following:
function LoadMenu() {
$("#pagedList").change(function () {
var id = $(this).val();
$("#url").val('/pages/' + id);
// remove the disabled attribute here
$('button.space').removeAttr('disabled');
});
}

Related

Angular2 - reset the value of a select after user changes it

I have a <select> which the user can change. Initially it has a value and when the user changes it I must prompt her "are you sure"? and in case the answer is NO then change back the <select>'s selected value to the previous one. The <select> is bound to a collection of objects, not values.
The best I could come up with so far is this:
in the html
<select [ngModel]="selectedObj" (ngModelChange)="onSelectedObjChanged($event)">
<option *ngFor="let obj of availableObjs" [ngValue]="obj">{{whatever}}<option>
</select>
in the code
onSelectedObjChanged(obj) {
if (prompt answer is no) {
let currentlySelectedObj = this.selectedObj;
this.selectedObj = null;
this.changeDetectorRef.detectChanges();
this.selectedObj = currentlySelectedObj;
this.changeDetectorRef.detectChanges();
}
}
This works, but is ugly. Why do I do it:
there seems to be no way to cancel the selection changed event in the DOM
when onSelectedObjChanged is called and the answer is "no", I need to somehow let angular know it has to refresh the binding target, i.e. the <select>...
...however I can't simply set this.selectedObj = this.selectedObj as the value doesn't change and there no change detected by angular; that's why I set it to null and back...
...however even that is not enough, I need to invoke changeDetectorRef.detectChanges() to notify angular of it
I'm sure there is a better and easier way to do this, it would be great if you could share some ideas.
Thanks!
Here's how I did it:
HTML:
<select [(ngModel)]="option"
#selectModel="ngModel"
(ngModelChange)="optionChanged($event)">
<option [ngValue]="null">PlaceHolder</option>
<option *ngFor="let o of options" [ngValue]="o">...</option>
</select>
Component:
#ViewChild('selectModel') private selectModel: NgModel;
optionChanged($event) {
//logic
this.selectModel.reset(null);
}
I use $event.target.value instead of $event. I send this.selectedObj = $event.target.value; and if failed change this.selectedObj = previousObject I don't need any change detection.
try this.selectedObj = obj.target.value; and than perform your condition.

Reload div with Select2 field using Ajax or JQuery [duplicate]

I'm using Select2 in a combination of dropdown menus. I have one menu for "Countries" and one for "States/Provinces". Depending on the country that is chosen, the "States/Provinces" dropdown changes in content. The states/provinces are pulled with ajax from a database and then displayed this way:
$display_output = '<select style="width:350px;" tabindex="2" name="state" id="state" data-placeholder="Choose a Country..."> ';
$display_output .= '<option value="" selected>Select a State</option> ';
while ($state_details = $this->fetch_array($sql_select_states))
{
$display_output .= '<option value="' . $state_details['id'] . '" ' . (($selected_value == $state_details['id']) ? 'selected' : ''). '>' . $state_details['s.name'] . '</option>';
}
$display_output .= '</select>';
So far, so good. All the provinces change correctly, however when it initially loads, the Select2 shows "undefined" for the states dropdown, even though I have it set as
data-placeholder="Choose a Country..."
I'm assuming it could be because on loading, the country selected is "United States" and it populates a list of states but none of them is default or selected. Is there any other way to define a default value so that it doesn't show "Undefined"?
And another (but less important) problem is that when someone chooses "United States" for example, and then chooses "Arizona", if the person then changes to "Canada" as the country, the state of "Arizona" still stays but when opening the dropdown the provinces of Canada are selectable. Is there any way to return it to the default value temporarily when someone selects another country, until a province is chosen again?
My loading code is currently just:
<script>
$(document).ready(function() { $("#state").select2(); });
</script>
Select 3.*
Please see Update select2 data without rebuilding the control as this may be a duplicate. Another way is to destroy and then recreate the select2 element.
$("#dropdown").select2("destroy");
$("#dropdown").select2();
If you are having problems with resetting the state/region on country change try clearing the current value with
$("#dropdown").select2("val", "");
You can view the documentation here http://ivaynberg.github.io/select2/ that outlines nearly/all features. Select2 supports events such as change that can be used to update the subsequent dropdowns.
$("#dropdown").on("change", function(e) {});
Select 4.* Update
You can now update the data/list without rebuilding the control using:
fooBarDropdown.select2({
data: fromAccountData
});
It's common for other components to be listening to the change event, or for custom event handlers to be attached that may have side effects. Select2 does not have a custom event (like select2:update) that can be triggered other than change. You can rely on jQuery's event namespacing to limit the scope to Select2 though by triggering the *change.select2 event.
$('#state').trigger('change.select2'); // Notify only Select2 of changes
select2 has the placeholder parameter. Use that one
$("#state").select2({
placeholder: "Choose a Country"
});
Use the following script after appending your select.
$('#state').select2();
Don't use destroy.
Finally solved issue of reinitialization of select2 after ajax call.
You can call this in success function of ajax.
Note : Don't forget to replace ".selector" to your class of <select class="selector"> element.
jQuery('.select2-container').remove();
jQuery('.selector').select2({
placeholder: "Placeholder text",
allowClear: true
});
jQuery('.select2-container').css('width','100%');
Got the same problem in 11 11 19, so sorry for possible necroposting.
The only what helped was next solution:
var drop = $('#product_1'); // get our element, **must be unique**;
var settings = drop.attr('data-krajee-select2'); pick krajee attrs of our elem;
var drop_id = drop.attr('id'); // take id
settings = window[settings]; // take previous settings from window;
drop.select2(settings); // initialize select2 element with it;
$('.kv-plugin-loading').remove(); // remove loading animation;
It's, maybe, not so good, nice and precise solution, and maybe I still did not clearly understood, how it works and why, but this was the only, what keeps my select2 dropdowns, gotten by ajax, alive.
Hope, this solution will be usefull or may push you in right decision in problem fixing
The solution:
Once the content is loaded via ajax you can no longer attack generically like eg ‘.select2’. Because now other elements have this class as the span generated by select2.
So after loading ajax you need to call a method to check if select2 is already instantiated and instantiate it individually.
jQuery('select.select2').each(function (i, obj) {
if (!jQuery(obj).hasClass("select2-hidden-accessible")) {
jQuery(obj).select2();
}
});
My article about
enter link description here
Suppose you are only interested in replacing select2 data:
$('#selector').html('').select2({
data: //new data
})
Initialize again select2 by new id or class like below
when the page load
$(".mynames").select2();
call again when came by ajax after success ajax function
$(".names").select2();

Ractive.js dynamically choose a Select option when a checkbox value changes

I have a checkbox which toggles state - giving a true or false value.
If the value is false, I'd like to hide the select box. If the value is true, I'd like to show the select box. This is all working 'out of the box' with just some template stuff - I simple do:
{{#if fooState }}
<select class="form-control" id="addFoo" value='{{selectedFoo}}'>
<option selected disabled>Select Foo</option>
{{#foo}}
<option value="{{_id}}|{{title}}">{{title}}</option>
{{/foo}}
</select>
{{/if}}
However, if I select a Foo option... this option remains selected when I set the fooState to false. I'd like to reset this - so the first option (select Foo) is selected - emptying the {{selectedFoo}} value.
I've tried doing stuff with observe, and events - but cant quite seem to grok this. When I punch my code into the console - I'm able to change the select option... but cant seem to trigger it from when the state changes.
Ok - so I finally figured it out... to do this, I don't lean on the data binding... I create a new on-change event and add that to the select.
<select class="form-control" id="addFoo" on-change='selectedFoo' >
<option></option>
</select>
ractive.on('selectedFoo' , function (event) {
var resourceArray = event.node.options[event.node.options.selectedIndex].value // Get our selected Foo option
resourceArray = resourceArray.split('|')
var FooData = {
a1: resourceArray[0],
a2: resourceArray[1],
a3: 'foo'
}
data.foo.push(resourceData);
});
So grab the data from the event - and then manually push it onto the array. This is completely self contained - it only affects this single select. Now does everything that I need to it to.
* Scrub this... it appears to break two way data binding. Please see above *
So I was watching a Ractive video - and had an epiphany! I was sort of stabbing around in the right area - but doing it all wrong:
ractive.on('fooStateToggle', function(event) {
console.log(event)
if (data.fooState) {
// Reset our select box! This took me ****ing ages to figure out... but its so, so, simple!
var addFooElem = ractive.nodes.addFoo;
addFooElem.selectedIndex = 0;
} else {
.....
}
});
So I needed to add some code in the event that's fired when the checkbox is clicked (fooStateToggle). Then if fooState is true... we grab the select box from the Ractive node list (not the dom - this is a virtual dom, so doing a direct selection wasn't going to work) and select the the first option by index. One gotcha... when the elem is hidden, its no longer available in the ractive.node list (makes perfect sense as its not being rendered to the page) so you have to catch it as soon as its rendered. You cant act upon it when its hidden - as it doesn't exist. I must say, I'm loving Ractive... I'm finding it so much quicker to pick up than React / Angular or any of the others. I love it! (thats probably going to get edited out by someone - but the guys who made this are awesome. Its made my dev so much easier!!)

KnockoutJS - populating second combobox based on value selected in first combobox

Below is my first piece of knockoutjs code i've written. In the code below, i have two list boxes. the first is populated after the page loads and works fine. What i want to do next is that when a user selects an item from the cmbDataSets listbox, i want to make a second ajax call to populate the 'instruments' property of my view model. later when the user selects an instrument, i want to make yet another call to fetch data that i will display in a grid (using slickgrid.js).
Right now, i'd like to understand what are the ways or best practice for accomplish this. i think i can simply add normal html/javascript selection change event handler on the first list box to accomplish this...but i'm not sure if that is the recommended way (i know it's not the MVVM way anyway). I feel that since selectedDataSet is an observable, i should be able to chain that to an event handler as well..no? My question is how? Can i define an onSelectedDataSetChange method on my viewmodel and if so, how do i 'hook' it into the actually selection change of the cmbDataSets control?
<div class="container">
<label for="cmbDataSets">Select list:</label>
<select id="cmbDataSets" data-bind="options: dataSets, optionsText:'descr', value:selectedDataSet, optionsCaption:'Choose' " class="form-control"></select>
<label for="cmbInstruments">Select instrument:</label>
<select id="cmbInstruments" data-bind="options: instruments, optionsText:'intrument', value:selectedInstrument, optionsCaption:'Choose' " class="form-control"></select>
</div>
<script type="text/javascript">
$(document).ready(function () {
var viewModel = {
dataSets: ko.observableArray(),
instruments: ko.observableArray(),
selectedDataSet: ko.observable(),
selectedInstrument: ko.observable()
}
$.ajax({
url: '/ds/sets',
type: "GET",
dataType: "json",
success: function (data) {
debugger;
console.log(data);
viewModel.dataSets(data);
}
});
ko.applyBindings(viewModel);
});
</script>
You can subscribe to the first boxes selectedOption observable and make a call whenever it changes.
selectedOption = ko.observable();
selectedOption.subscribe(function (newValue) {
secondBoxSource(ajaxCallFunction(newValue));
});
Where ajaxCallFunction() is the function you use to fetch the data for the second box, and newValue is the newly selected value from the first box.
Mike.
Check this code, for setting change event in the View:
<select data-bind="event: { change: selectionChanged }"></select>
and then a proerty in the ViewModel:
selectionChanged: function(event) { }
Is this is what you were searching for? Other than this, I have a small suggestions - SelectedDataSet and selectedInstrument can be also observable arrays. The difference is that you are going to use not the 'value' biding, but the 'selectedOptions' one. This will help you when you have multiple selection, but even when it's a single one, it's a better option, I think.

populate and disable text field depending on dropdown

Unfortunately i'm not too familiar with javascript/jQuery. I have a form with a dropdown. What i need to do is to populate a text field depending on the selection of the dropdown. First voice of the dropdown is "other" so the text field must be writable, then from the second i want to assign a value automatically and disable the text field.
The value of the dropdown will be saved in the db so it must remains the name of the option.
I found several solutions with google but none of them fits my needs...hope someone could help me.
To create the functionality you're looking for, there are a few basic things you'll need to learn.
jQuery Selectors
First, if you aren't already familiar with jQuery's selector syntax, learn about it here.
The .change() Event
Next, you'll need to know how to bind to the dropdown menu's .change event. One way to do this is $('#dropdownId').change(function() { ... });, which is just a shortcut for $('#dropdownId').on('change', function() { ... }); . Within the callback functions, you can access the dropdown element with this and as a result, the jQuery object with $(this).
We can then grab the dropdown's value with $(this).val() and use some basic logic to enable/disable the textbox and set its value.
Enabling/Disabling the textbox
In order to enable/disable the textbox, you can use: $('#txt').removeAttr('disabled');and$('#txt').attr('disabled', 'true');` respectively.
Example
I've combined all of these for you in an example fiddle to show you how you can put these together in this jsFiddle. Let me know if you have any questions about how it works :)
Here is the fiddle for you...
http://jsfiddle.net/G3V3v
HTML:
<select id="ddl">
<option value="0">[ Other ]</option>
<option value="1">First</option>
<option value="2">Second</option>
</select>
<input id="txt" />
jQuery:
$('#ddl').change(function() {
if ($(this).val() == 0) {
$('#txt').val('').removeAttr("disabled").focus();
} else {
$('#txt').val($(this).children('option:selected').text());
$('#txt').attr("disabled", "disabled");
}
});

Categories