Knockout.js - Updating a textbox when a dropdown has changed - javascript

I'm trying update a textbox when I change the value of a select.
Now, I know this is fairly simple however I'm not looking to update the textbox with easy to get data.
Here's what I can do so far:
Catch the change event
Get the ID from the Select dropdown
Here's what I want to do:
Use the selected ID to return a property value from inside an array of objects inside my viewmodel. However, the ID does not match the array index (i.e. the selected ID may be "43" but the index is 0).
Not much point in posting my Knockout code as it's fairly basic so instead I'll post my VM structure.
ViewModel
--> Property1
--> Property2
--> Array
--> Object[0]
--> "Property to match with the selected ID"
--> "Property that I want to return"
--> Object[1]
Not really sure how much sense this is making, hope it makes some.
Any other info can be provided.
Thanks!
EDIT
VM
var PurchaseOrderViewModel = function (data) {
var self = this;
self.UpdateCurrency = function (data, event) {
//
}
self.UpdateSupplierContactDetails = function (data, event) {
//
}
ko.mapping.fromJS(data, {}, self);
}
$(document).ready(function () {
var viewModel = new PurchaseOrderViewModel(#Html.Raw(jsonString));
ko.applyBindings(viewModel);
});
EDIT #2
Managed to get a working solution, in case anyone else has issues here is how I worked around it.
var contact = ko.unwrap(ko.utils.arrayFirst(self.AllSupplierContacts(),
function (item) {
return ko.unwrap(item.Id) === newID;
}).BusinessTelephoneNumber);

This answer has two parts: the code I think you're looking for (1), and the code I think you should write (2).
1. Finding an item that matches an id
ko.applyBindings(new function() {
this.ids = ["A", "B", "C", "D"];
this.selectedId = ko.observable();
this.items = [
{ key: "A", value: 1 },
{ key: "B", value: 2 },
{ key: "C", value: 3 },
];
this.selectedValue = ko.pureComputed(function() {
var selectedId = this.selectedId();
// Find the object in items of which the property
// `key` matches the `selectedId` and return it
var match = this.items.find(function(item) {
return item.key === selectedId;
});
return match ? match.value : "No item found";
}, this);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: ids, value: selectedId"></select>
<div>
Your selected value: <strong data-bind="text: selectedValue"></strong>
</div>
2. Binding the actual elements to the select:
Knockout's options binding does many things out of the box. You probably don't need to store ids and items separately. By telling the binding which property it should render in the dropdown (optionsText), and which to store as a value (optionsValue), you'll need a lot less code to do the same thing:
ko.applyBindings(new function() {
this.items = [
{ key: "A", value: 1 },
{ key: "B", value: 2 },
{ key: "C", value: 3 },
{ key: "D", value: 4 }
];
this.selectedValue = ko.observable();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: items,
optionsText: 'key',
optionsValue: 'value',
value: selectedValue"></select>
<div>
Your selected value: <strong data-bind="text: selectedValue"></strong>
</div>

The whole issue of "having to look up an ID in an array" can be side-stepped by not working with IDs at all, but with the array items themselves.
function MyList(params) {
var self = this;
// observables
self.items = ko.observableArray();
self.selectedItem = ko.observable();
// init
ko.mapping.fromJS(params, {}, self);
// post-init
self.items.sort(function (a, b) {
return ko.unwrap(a.key) < ko.unwrap(b.key) ? -1 : 1;
});
}
ko.applyBindings(new MyList({
items: [
{ key: "D", id: 4 },
{ key: "A", id: 3 },
{ key: "B", id: 2 },
{ key: "C", id: 1 }
]
}));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<select data-bind="
optionsCaption: 'Please select...',
options: items,
optionsText: 'key',
value: selectedItem
"></select>
<div data-bind="with: selectedItem">
Your selected value: <strong data-bind="text: id"></strong>
</div>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

Related

knockoutJs ko.utils.arrayFirst not allowing duplicate values as results

I am new to knockoutJs, as i am trying to display the selected values by binding. But am facing issues with duplicate values.
For example:
As per the below example snippet, If i select one from the dropdown, the binding result is displaying name "one" as selected, this is correct.
{name:"one",price:32.50}, {name:"two",price:32.50},
After that if I select other option from drop down i.e name two, the binding result is not displaying name two as selected, instead it is keep displaying the name="one" only, which is in-correct.
Observation: I see that this is happening due to the same price set for all the option values, if I update them with different prices the options values are binding properly.
Here my confusion is that why the binding logic is not applying properly when the price value is same but the name is different.
I am trying to achieve this by below code.
Html
<select data-bind="options: beforeEventPedersensDropoffCustomerLocation,optionsCaption: 'Please Choose Closest Location',
optionsText: 'name', optionsValue: 'price', value: selectedPricebepdcl" id="before_event_pedersens_dropoff_customer_location_time" ></select>
Js
self.beforeEventPedersensDropoffCustomerLocation = [
{name:"one",price:32.50},
{name:"two",price:32.50},
{name:"three",price:32.50},
{name:"four",price:32.50},
{name:"five",price:32.50},
{name:"six",price:32.50},
{name:"seven",price:0}
];
self.selectedPricebepdcl = ko.observable("");
console.log()
self.beforeEventVal = ko.computed(function() {
if(self.selectedPricebepdcl() !== "")
return ko.utils.arrayFirst(self.beforeEventPedersensDropoffCustomerLocation, function(time) {
return self.selectedPricebepdcl() === time.price;
});
return null;
}, this);
Result
<p data-bind="with: beforeEventVal">
<span data-bind="text: name"></span>
</p>
<p data-bind="with: beforeEventVal">
<span data-bind="text: price"></span>
</p>
Can anyone help me on this.
The problem is that you have set optionsValue: 'price', so the only information you have about which item is selected is the price. Then you try to use that to find the selected item from among the available items, but you cannot do that because it is not a unique identifier.
Instead, if you don't specify optionsValue, Knockout will use the entire item as the value of the select. That also lets you do away with looking up the selected value, because you have the selected value.
function VM() {
self = this;
self.beforeEventPedersensDropoffCustomerLocation = [{
name: "one",
price: 32.50
},
{
name: "two",
price: 32.50
},
{
name: "three",
price: 32.50
},
{
name: "four",
price: 32.50
},
{
name: "five",
price: 32.50
},
{
name: "six",
price: 32.50
},
{
name: "seven",
price: 0
}
];
self.selectedBepdcl = ko.observable("");
self.selectedName = ko.pureComputed(() => {
const sb = self.selectedBepdcl();
return sb && sb.name ? sb.name : '';
});
}
ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="options: beforeEventPedersensDropoffCustomerLocation,
optionsCaption: 'Please Choose Closest Location',
optionsText: 'name',
value: selectedBepdcl" id="before_event_pedersens_dropoff_customer_location_time">
</select>
<p data-bind="with: selectedBepdcl">
<span data-bind="text: name"></span>
</p>
<p data-bind="with: selectedBepdcl">
<span data-bind="text: price"></span>
</p>
Pretend this is hidden:
<input data-bind="value: selectedName">

How to auto select users state in data-bind options select in Knockout

i have a drop down of states and their ID:
<select data-bind="options: States, optionsText: 'text', value: SelectedState"></select>
Javascript
function ViewModel() {
this.States = ko.observableArray(states);
this.SelectedState = ko.observable(usersState);
};
var states = [
{ value: 10, text: "California" },
{ value: 3, text: "New York" },
{ value: 9, text: "Florida" }
];
ko.applyBindings(new ViewModel());
usersState is a variable that may or maynot contain the users info. By default its null. But if the user has already logged in then it should populate with the users selected state. For this example, the users has logged in and their select state is 9 for florida.
so i declared usersState = 9; at the top.
What i am trying to do is simply auto select Florida in the drop down based on the users info.
not sure why its not selecting it. Here is my fiddle: http://jsfiddle.net/neosketo/sw9dzjk1/2/
The SelectedState refers to a state object. Your initial selection is a number. You'll have to find the state object corresponding to the number:
var usersState = 9;
// This method finds an object by value property
var findStateById = function(states, id) {
return states.find(function(state) {
return state.value === id;
});
};
function ViewModel() {
this.States = ko.observableArray(states);
// In this example, SelectedState is an object with a value and text property
this.SelectedState = ko.observable(findStateById(states, usersState));
};
// Test data
var states = [{
value: 10,
text: "California"
}, {
value: 3,
text: "New York"
}, {
value: 9,
text: "Florida"
}];
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: States, optionsText: 'text', value: SelectedState"></select>
(Note that I used Array.prototype.find which isn't supported by all browsers)
Alternatively, you could use the optionsValue option to tell knockout to use the value property to match selection to options. Personally, I prefer using the actual object: knockout being able to work with references to real instances rather than using strings makes developing easier.
var usersState = 9;
function ViewModel() {
this.States = ko.observableArray(states);
// In this example, SelectedState is a number
this.SelectedState = ko.observable(usersState);
};
var states = [{
value: 10,
text: "California"
}, {
value: 3,
text: "New York"
}, {
value: 9,
text: "Florida"
}];
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: States,
optionsText: 'text',
optionsValue: 'value',
value: SelectedState"></select>

Angularjs Select Option set to first item did not work

I am working with angular and semantic ui. I am trying to make a selection of Y and N through a select option. Basically i just want the first item was selected when the page show up. Tried many ways but i couldn't make it works.
Please take a look at this plunker.
angular.module('myapp', [])
.controller('testctrl', function ($scope){
$scope.add = {};
$scope.Consigns = [{value: 'N',label: 'N'}, {value: 'Y',label: 'Y'}];
$scope.add.consign = $scope.Consigns[0].label;
})
.controller('testctrl1', function ($scope){
$scope.add = {};
$scope.Consigns1 = [{value: 'N',label: 'N'}, {value: 'Y',label: 'Y'}];
$scope.add.consign1 = $scope.Consigns1[0].label;
});
https://plnkr.co/edit/cHcLd14xKFxLMS4uy0BM?p=preview
Print the model value in default placeholder. Rather than sending the label value in $scope.add.consign you could send the whole object and print whats required.
Working plunker: https://plnkr.co/edit/XeuiS7p3K1OOx5nHL9c5?p=preview
javascript:
$scope.ListOrder =
[
{ Name: "price", Id: 1 },
{ Name: "exist", Id: 2 },
{ Name: "Sale", Id: 3 },
{ Name: "New", Id: 4 }
];
$scope.Order = { Name: "exist", Id: 1 };
HTML:
<select ng-model="Order" ng-options="obj.Name for obj in ListOrder"></select>
Remove
<script>
$('.ui.dropdown').dropdown();
</script>
and also change select tag to this
<select ng-model="add.consign" class="ui fluid dropdown" ng-options="x.label as x.label for x in Consigns">
<option value=""></option>
</select>

How can I call different functions based on the value when a <select> value changes?

I want to call different function on changing the select option
Here is the markup:
<p>With every selection change I want a different function to be called</p>
<select data-bind="options: availableMeals, optionsText: 'name', value: selectedMeal, optionsValue: 'value', event: {change: onChange}">
</select>
Here is my viewmodel:
function ReservationsViewModel() {
var self = this;
self.availableMeals = ko.observableArray(
[
{name: "Standard (sandwich)", value: 0},
{name: "Premium (lobster)", value: 34.95},
{name: "Ultimate (whole zebra)",value: 290}
]
);
self.selectedMeal = ko.observable(self.availableMeals()[0]);
// i want this when i change to sandwitch
self.onChange = function() {
alert("for sandwitch");
};
// i want this when i change to lobster
self.onChange1 = function() {
alert("for lobster");
};
//i want this when i change to ultimate
self.onChange2 = function() {
alert("for whole zebra");
};
}
ko.applyBindings(new ReservationsViewModel());
I know that I have only bind the onChange function with change event. What could be the way to call three different functions on different selections?
Here is the demo fiddle: http://jsfiddle.net/mLv42zkL/
Use one function onChange and then call other functions depending on the value of selectedMeal.
For example:
function ReservationsViewModel() {
var self = this;
self.availableMeals = ko.observableArray(
[{
name: "Standard (sandwich)",
value: 0
}, {
name: "Premium (lobster)",
value: 34.95
}, {
name: "Ultimate (whole zebra)",
value: 290
}]
);
self.selectedMeal = ko.observable(self.availableMeals()[0]);
self.onChange = function() {
switch (self.selectedMeal()) {
case 0:
self.sandwichSelected();
break;
case 34.95:
self.lobsterSelected();
break;
case 290:
self.zebraSelected();
break;
}
};
self.sandwichSelected = function() {
alert("for sandwich");
};
self.lobsterSelected = function() {
alert("for lobster");
};
self.zebraSelected = function() {
alert("for whole zebra");
};
}
ko.applyBindings(new ReservationsViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<p>With every selection change I want a different function to be called</p>
<select data-bind="options: availableMeals, optionsText: 'name', value: selectedMeal, optionsValue: 'value', event: {change: onChange}">
</select>
Fiddle Demo

How do I construct the proper view model (with multiple dependencies) in KnockoutJS?

Here is a subset of the markup I am using:
<div id="item_one"></div>
<div id="item_two"></div>
<div id="item_three"></div>
<p id="result_one">0</p>
<p id="result_two">0</p>
<p id="result_three">0</p>
The desired behaviors are:
When you click a div, the corresponding text of the p tag is toggled from 0 to 1.
The text of the p tags is to be concatenated into a string, e.g., click the second item and the resulting string would be "010".
There is an array of eight items, with binary strings as the key. As clicks are made, the selected item in the array changes.
This seems like a good use of knockout, but I am a complete noob. How do I set up the proper dependencies?
Here is a sample for one way to do it: http://jsfiddle.net/rniemeyer/XqDsy/
For convenience, I created a little "binaryObservable" that exposes a toggle function.
function binaryObservable(initialValue) {
var result = ko.observable(initialValue);
result.toggle = function() {
result(result() === "1" ? "0" : "1");
};
return result;
}
function ViewModel() {
this.one = binaryObservable("0");
this.two = binaryObservable("0");
this.three = binaryObservable("0");
this.combined = ko.dependentObservable(function() {
return this.one() + this.two() + this.three();
}, this);
this.choices = {
"000": { id: 0, value: "000" },
"001": { id: 1, value: "001" },
"010": { id: 2, value: "010" },
"011": { id: 3, value: "011" },
"100": { id: 4, value: "100" },
"101": { id: 5, value: "101" },
"110": { id: 6, value: "110" },
"111": { id: 7, value: "111" }
};
this.selectedChoice = ko.dependentObservable(function() {
var combined = this.combined();
return combined ? this.choices[combined] : {};
}, this);
}
ko.applyBindings(new ViewModel());
Then the HTML might look like:
<div id="item_one" data-bind="click: one.toggle">option one</div>
<div id="item_two" data-bind="click: two.toggle">option two</div>
<div id="item_three" data-bind="click: three.toggle">option three</div>
<hr/>
<p id="result_one" data-bind="text: one">0</p>
<p id="result_two" data-bind="text: two">0</p>
<p id="result_three" data-bind="text: three">0</p>
<hr/>
<p data-bind="text: combined"></p>
<hr/>
Selected choice: <span data-bind="text: selectedChoice().id"></span>
Im far from an expert but something like this ?
jsFiddle

Categories