on Change event in select with knockout - javascript

I have a problem how to call onchanges knock js to my select option, i already have a function and html, but when i choose the select option, nothing changes
<select data-bind="event:{change:setSelectedStation() },
options: seedData,
optionsText: 'text',
optionsValue: 'value'">
</select>
here is my function
setSelectedStation: function(element, KioskId){
this.getPopUp().closeModal();
$('.selected-station').html(element);
$('[name="popstation_detail"]').val(element);
$('[name="popstation_address"]').val(KioskId);
$('[name="popstation_text"]').val(element);
// console.log($('[name="popstation_text"]').val());
this.isSelectedStationVisible(true);
},

Use knockout's two-way data-binds instead of manually subscribing to UI events.
Knockout's value data-bind listens to UI changes and automatically keeps track of the latest value for you.
Instead of replacing HTML via jQuery methods, you use text, attr and other value bindings to update the UI whenever your selection changes.
If you want to perform additional work when a selection changes (e.g. closing a pop up), you subscribe to the selected value.
var VM = function() {
this.seedData = [
{
text: "Item 1",
data: "Some other stuff"
},
{
text: "Item 2",
data: "Something else"
},
{
text: "Item 3",
data: "Another thing"
}
];
this.selectedItem = ko.observable();
this.selectedItem.subscribe(function(latest) {
console.log("Input changed");
}, this);
};
ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="
value: selectedItem,
options: seedData,
optionsText: 'text'">
</select>
<!-- ko with: selectedItem -->
<p>
Your selection: <span data-bind="text: data"></span>
</p>
<!-- /ko -->

Related

Access select2 HTML options from knockout custom binding in order to disable them

I am trying to access the option elements from a select2 dropdown list using a Knockout custom binding in order to disable some of them (some of the options). The custom binding is:
ko.bindingHandlers.select2 = {
after: ["options", "value"],
update: function (el, valueAccessor, allBindingsAccessor, viewModel) {
var allBindings = allBindingsAccessor();
var select2 = $(el).data("select2");
}
};
and the HTML part is:
<div style="width: 350px;">
<select style="width: 100%;" data-bind="value: attributiSelezionati, options: data, valueAllowUnset: true, optionsText: 'text', optionsValue: 'id', select2: { placeholder: 'Select an option...', allowClear: true, multiple: true}"></select>
</div>
where the data array is:
this.data = ko.observableArray([]);
this.data.push(new Item(1, "Item 1"));
this.data.push(new Item(2, "Item 2"));
this.data.push(new Item(2, "Item 22"));
this.data.push(new Item(3, "Item 3"));
this.data.push(new Item(null, "Item 4"));
class Item {
id: KnockoutObservable<number> = ko.observable<number>();
text: KnockoutObservable<string> = ko.observable<string>();
constructor(Id: number, Text: string) {
this.id(Id);
this.text(Text);
}
}
I can see the data when I hover over the el element but I do not know how to access it programmatically. Does anyone know how to get these items?
It should be in valueAccessor()
valueAccessor: This represents a JavaScript function that can be used to access the current property or expression involved in this binding. Because Knockout allows you to use either a view model property directly (such as "data-bind='enabled: isEnabled'"), or an expression (such as "data-bind='enabled: firstName.length > 0'"), there's a utility function that will "unwrap" and give you the actual value used in the binding. Incidentally, this function is called "ko.unwrap."
var val = ko.unwrap(valueAccessor());
//val.options;

Knockout - applying styles to the selected item in a Bootstrap Select

So this is piling libraries on top of libraries, but I'm not sure what else to do.
Our application has a number of drop-down elements all of which are Bootstrap Select objects. These replace the standard set of option tags inside the select with a complex series of other elements that give you much greater control over the styling of the children and make them searchable.
Most of these objects exist as reusable components with an HTML view and a Typescript ViewModel, bound together with Knockout.
A number of these menus have icons next to the text. This is handled with optionsAfterRender. Here's an example.
View:
<select
data-bind="options: items,
value: selectedValue,
optionsText: 'value',
optionsValue: 'id',
selectPicker: {},
optionsAfterRender: applyOptionAttributes">
</select>
ViewModel:
export default class SelectComponent {
selectedValue: KnockoutObservable<string>;
items: KnockoutObservableArray<SelectOption>
constructor(koObservable: KnockoutObservable<string>) {
// items fetched and bound
}
applyOptionAttributes(option: Node, item: SelectOption): void {
ko.applyBindingsToNode(option, { attr: { "data-content": `<img src="${item.iconurl}" />`, title: item.value } }, item);
}
}
interface SelectOption {
value: string;
id: string
iconurl: string;
}
And this is fine. However, because of the way Bootstrap Select styles the items inside it, the icon is not applied to the currently selected item - it's only displayed when the user clicks on the menu and it pops up.
Now, of course, we have a requirement to display the icon in currently selected item too. But I don't know how to get that element to bind to it. I can't fetch it directly because of the view-viewmodel pattern. It doesn't seem to be among the nodes passed by optionsAfterRender.
How can I get hold of it to style it?
EDIT: pretty sure this is a bug in bootstrap-select. Have raised an issue
https://github.com/snapappointments/bootstrap-select/issues/2129
You could try to fix this by preventing the post-processing of the options:
Replace the options binding with a foreach binding in the select element, binding each option with the appropriate ko-bindings.
Make sure the selectPicker binding has its descendant bindings bound before calling selectpicker on the element.
Profit!
ko.bindingHandlers['selectPicker'] = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
ko.applyBindingsToDescendants(bindingContext, element);
$(element).selectpicker();
return { controlsDescendantBindings: true };
}
}
ko.applyBindings({
selectedValue: ko.observable(3),
options: [
{ id: 1, name: 'Mustard', dc: '<span class="badge badge-warning">Mustard</span>' },
{ id: 3, name: 'Ketchup', dc: '<span class="badge badge-danger">Ketchup</span>' },
{ id: 4, name: 'Relish', dc: '<span class="badge badge-success">Relish</span>' }
]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.3/css/bootstrap-select.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.3/js/bootstrap-select.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="selectPicker, value: selectedValue">
<!-- ko foreach: options -->
<option data-bind="text: name, attr: { value: id, 'data-content': dc }"></option>
<!-- /ko -->
</select>

Keep knockout select menu open when clicking on options inside

How can i prevent the select menu from closing when clicking inside, and when clicking outside the menu it should close itself
enter code herehttps://jsfiddle.net/1jekvsb6/1/
i tried to use this reference
https://knockoutjs.com/documentation/click-binding.html
that other people have pointed but i couldnt get this to work... any help greatly appreciated!
hi john In case multi select prevent closing and outside click simple remove the items
and at click event add the items . I display just multiple selection
var model = function() {
var self = this;
self.arr = ko.observableArray([
{ Type: "Item1" },
{ Type: "Item2" },
{ Type: "Item3" },
{ Type: "Item4" },
{ Type: "Item5" }
])
}
var theModel = new model();
ko.applyBindings(theModel, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div id="container">
<select multiple style="width: 150px;" size=5 data-bind="options: arr, optionsText: 'Type', optionsValue: 'Type', click: function() {}, clickBubble: false">
<option data-bind="click: function() {return false;}, clickBubble: true"></option>
</select>
</div>

Get selected text on dropdown change event in Knockout.js

I am trying to get the text of selected index in dropdown using knockout.js,
following is my HTML
<select name="" id="management" class="form-control" data-bind="value: ManagementCompanies,optionText:ManagementCompaniestxt">
<option value="0">---Select---</option>
<option value="1">abcd</option>
<option value="2">efgh</option>
</select>
following is my Model binding:
var FilterViewModel = {
ManagementCompanies: ko.observable(''),
ManagementCompaniestxt:ko.observable('')
}
FilterViewModel.ManagementCompanies.subscribe(function (newValue) {
alert(FilterViewModel.ManagementCompaniestxt());
});
ko.applyBindings(FilterViewModel, window.document.getElementById("SelectFilters"));
i have tried to bind using Text as well but didn't work.
how can i get selected text abcd in subscribe event?
thanks
It's a bit weird that you're trying to get data from your view to your viewmodel. Usually, your view is a representation of your viewmodel. It's better to have the data needed to render your <select> in your model, and use knockout's options data-bind to render it.
Here's how you can do this:
var FilterViewModel = {
ManagementCompanies: ko.observable(''),
ManagementCompaniestxt: ko.observable(''),
options: [
{ text: "---Select---", value: 0 },
{ text: "abcd", value: 1 },
{ text: "efgh", value: 2 }]
}
FilterViewModel.ManagementCompanies.subscribe(function(newValue) {
console.log(newValue.text);
});
ko.applyBindings(FilterViewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="value: ManagementCompanies,
options:options,
optionsText: 'text'">
</select>

Knockout: Select in simpleGrid example

I am using the knockout simple grid found here:
http://knockoutjs.com/examples/grid.html
I want to be able to add a select into the grid, which has a data-bind attribute assigned to an object array in my vm.
So I have added another column from the example:
this.gridViewModel = new ko.simpleGrid.viewModel({
data: this.items,
columns: [
{ headerText: "Item Name", rowText: "name" },
{ headerText: "Sales Count", rowText: "sales" },
{ headerText: "Price", rowText: function (item) { return "$" + item.price.toFixed(2) } },
*{ headerText: "Select", rowText: function (item) { return "<select data-bind=\"options:items, optionsText: 'name', optionsValue: 'name'\"></select>" } }*
],
pageSize: 4
});
And changed the text attribute to html within the control:
<td data-bind=\"*html*: typeof rowText == 'function' ? rowText($parent) : $parent[rowText] \"></td>\
The Selects appear, but not populated with data from my object array.
JSFiddle found here:
http://jsfiddle.net/vwj2p/1/
(I have pasted in the code from the simple grid above as I made a change to the simplegrid code).
{ headerText: "Select", rowText: function (item) { return "<select data-bind=\"options:$root.items, optionsText: 'name', optionsValue: 'name'\"></select>" } }
I'm assuming each item object doesn't have an items property and you're trying to reference the viewModel's items array? If so, change your code to the above.
This still won't work, however. If you look at the html binding documentation, you'll see that it's only going to spit out static html. During the binding process when this is all getting rendered, KO doesn't applyBindings to the generated HTML.
I tried playing around with the code a bit to try and do ko.applyBindingsToDescendants(viewModel, {td element}), where {td element} is a reference to the parent element with the html binding on it, when the items observableArray updated but that didn't seem to do anything.
Bottom line, I don't think you're going to get this to work without doing a lot of plumbing work to the simpleGrid. It is just a simple grid, after all.

Categories

Resources