Knockout, previous value of select / dropdown - javascript

I want to know what the previous value is from a Dropdown list.
In the following html I can set the Options and the currently selected.
<select data-bind="options: group_128,
optionsText: 'description',
value: selectedgroup_128,
event: { change: selectionChanged_group_128 }">
</select>
in the Javascript / viewModel I do :
selectionChanged_group_128 = function (data, event) {
self.addItemClicked2(self.selectedgroup_128, event)
};
At this point I want to know what the previous selected item was to send it to the addItemClicked2.

You could subscribe to the observable to get the value before it changed:
self.selectedgroup_128.subscribe(function(oldValue) {
self.selectedgroup_128.previousValue = oldvalue;
}, null, "beforeChange");
Now you can get the previous value like this:
self.selectedgroup_128.previousValue

Why not just change your model to store the new value as previous value?
http://jsfiddle.net/uLeDP/
var ViewModel = function() {
this.group_128 = ko.observable([{description:"first"},{description:"second"}]);
this.selectedgroup_128 = ko.observable("first");
this.prevgroup_128 = null;
this.selectionChanged_group_128 = function(val) {
alert("Now I'm " + this.selectedgroup_128().description + " but I was " + this.prevgroup_128);
this.prevgroup_128 = this.selectedgroup_128().description;
}
};

Related

createElement function not working with MAC Safari

I have below code to create Drop-down:
Below code for HTML to render Drop-down as:
<input class="form-control selectedTextBox mobile-space" list="rider" type="text" id="ridername" placeholder="FirstName LastName"
data-bind="trimedValue: item().Name, datalist: {
options: app.viewModel.riderProfiles(),
optionsValue: 'Id',
optionsText: 'Name',
value: app.viewModel.selectedRiderId
}" />
Below is Knockout.js handler:
ko.bindingHandlers.datalist = (function () {
function getVal(rawItem, prop) {
var item = ko.unwrap(rawItem);
return item && prop ? ko.unwrap(item[prop]) : item;
}
function findItem(options, prop, ref) {
return ko.utils.arrayFirst(options, function (item) {
return ref === getVal(item, prop);
});
}
return {
init: function (element, valueAccessor, allBindingsAccessor) {
var setup = valueAccessor(),
textProperty = ko.unwrap(setup.optionsText),
valueProperty = ko.unwrap(setup.optionsValue),
dataItems = ko.unwrap(setup.options),
myValue = setup.value,
koValue = allBindingsAccessor().value,
datalist = document.createElement("DATALIST");
// create an associated <datalist> element
datalist.id = element.getAttribute("list");
document.body.appendChild(datalist);
// when the value is changed, write to the associated myValue observable
function onNewValue(newVal) {
var dataItems = ko.unwrap(setup.options),
selectedItem = findItem(dataItems, textProperty, newVal),
newValue = selectedItem ? getVal(selectedItem, valueProperty) : void 0;
if (ko.isWriteableObservable(myValue)) {
myValue(newValue);
}
}
// listen for value changes
// - either via KO's value binding (preferred) or the change event
if (ko.isSubscribable(koValue)) {
koValue.subscribe(onNewValue);
} else {
ko.utils.registerEventHandler(element, "change", function () {
onNewValue(this.value);
});
}
// init the element's value
// - either via the myValue observable (preferred) or KO's value binding
if (ko.isObservable(myValue) && myValue()) {
element.value = getVal(findItem(dataItems, valueProperty, myValue()), textProperty);
} else if (ko.isObservable(koValue) && koValue()) {
onNewValue(koValue());
}
},
update: function (element, valueAccessor) {
var setup = valueAccessor(),
datalist = element.list,
dataItems = ko.unwrap(setup.options),
textProperty = ko.unwrap(setup.optionsText);
// rebuild list of options when an underlying observable changes
datalist.innerHTML = "";
ko.utils.arrayForEach(dataItems, function (item) {
var option = document.createElement("OPTION");
option.value = getVal(item, textProperty);
datalist.appendChild(option);
});
ko.utils.triggerEvent(element, "change");
}
};})();
And with only MAC(OS) & Safari (Web-Browser) below error message is shown as:
Message: Unable to process binding "datalist: function () {return { options:app.viewModel.riderProfiles(),optionsValue:'Id',optionsText:'Name',value:app.viewModel.selectedRiderId} }"
Message: undefined is not an object (evaluating 'u.innerHTML=""')
The HTML element contains a set of elements that represent the values available for other controls.
But "Safari" browser does not support it.

Odd behaviour of dropdown in Angular JS

I am making hybrid app using Angular JS, wherein there is an page which has two dropdown (select controls).
The thing should be,When I select the first dropdown the second one automatically should fill based on the data fetched on change of first doropdown; but what happens is on change of first dropdown the data is fetched but it is not getting bind to second dropdown immediately though the model of second dropdown gets the data fetched on selection of first dropdown, instead what happens is when i again change the first dropdown selection, the previous data gets bind to the second dropdown.
Below is my code for the same -
Car Make dropdown -
<select name="make"
ng-options="item.MakeId as item.Make for item in memberdetailData.VehicleData"
ng-model="memberdetailData.selected_Make_ID"
ng-change="vehiclemakeselected()">
Car Model Dropdown -
<select name="model" ng-disabled="memberdetailData.selected_Make_ID === {}"
ng-options="item.ModelId as item.Model for item in memberdetailData.Vehicle_Model"
ng-model="memberdetailData.selected_Model"></select>
Controller code -
$scope.vehiclemakeselected = function () {
console.log($scope.memberdetailData.selected_Make_ID);
//console.log($scope.memberdetailData.selected_Make_ID);
db_factory.selectVehicleMasterData('select ModelId,Model from tbl_vehicle WHERE MakeId ="' + $scope.memberdetailData.selected_Make_ID + '";', function (res) {
console.log("this is respo");
//console.log(res);
$scope.memberdetailData.Vehicle_Model = null;
$scope.memberdetailData.Vehicle_Model = res;
console.log($scope.memberdetailData.Vehicle_Model);
// console.log($scope.memberdetailData.Vehicle_Model);
$scope.memberdetailData.selected_Model = null;
$scope.memberdetailData.selected_Model = $scope.memberdetailData.Vehicle_Model[0].ModelId;
}, function () {
// globalFactory.showAlert('Data Error', 'No Salutation Master Found, Kindly Sync Salutation Master');
});
}
DBFactory -
db_factory_obj.selectVehicleMasterData = function (query, callBack, errorcall) {
var result = [];
db_factory_obj.db.transaction(function (tx) {
tx.executeSql(query, [], function (tx, rs) {
for (var i = 0; i < rs.rows.length; i++) {
var row = rs.rows.item(i)
result[i] = {
MakeId: row['MakeId'],
Make: row['Make'],
ModelId: row['ModelId'],
Model: row['Model']
}
}
////console.log(result);
callBack(result); // <-- new bit here
}, errorcall);
});
}
Please help.
Thanks.
Krunal

knockoutjs subscribe not firing

I have the following client-side code:
var ProfileManager = function () {
self.SelectedLanguage = ko.observable();
self.SelectedLanguage.subscribe(function (newValue) {
alert("The person's new name is " + newValue);
});
var bindUIwithViewModel = function (viewModel) {
ko.applyBindings(viewModel);
};
}
and I later do bindUIwithViewModel(self);.
and a HTML select bound to SelectedLanguage:
<select id="selectAvailableLanguages" class="form-control language-select" data-bind="options: AvailableLanguages, optionsText: 'Code', value : SelectedLanguage"></select>
The select gets populated successfully, the value inside SelectedLanguage observable changes, but the alert just won't show up. Any ideas?
Also, don't know if related but the observe array inside __ko.mapping_ is an array[0]..
Please check the fiddle. Note, "AvailableLanguages" and "SelectedLanguage" properties should exist in the same context, i.e. belong the binded view model.
I've modified your JS code:
var ProfileManager = function () {
self.SelectedLanguage = ko.observable();
self.SelectedLanguage.subscribe(function (newValue) {
alert("The person's new name is " + JSON.stringify(newValue));
});
self.AvailableLanguages = [ { Code: 'c++', Person: 'John' }, { Code: 'c#', Person: 'Mark' } ]
}
ko.applyBindings(new ProfileManager());

Two Select computed Knockout

I try to binding two computed select with Knockout:
- the first select(DropDownLinee) is filled when on page load
- the second select(DropDownCorse) is filled when the user select an item on the first select
This is the example:
<select id="DropDownLinee" data-bind="options: ArrayLinee, optionsText: 'NomeLinea', optionsValue: 'NomeLinea', value: selectedLinea " data-toggle="dropdown"></select>
<select id="DropDownCorse" data-bind="options: ArrayCorse, optionsText: 'CodiceCorsa', optionsValue: 'CodiceCorsa', value: selectedCorsa " data-toggle="dropdown"></select>
function LineeViewModel() {
var self = this;
self.selectedLinea = ko.observable();
self.selectedCorsa = ko.observable();
self.ArrayLinee = ko.observableArray([]);
self.ArrayCorse = ko.observableArray([]);
$.getJSON('/Home/GetLines', function (data) {
self.ArrayLinee(data);
});
self.ArrayCorse = ko.computed(function () {
$.getJSON('/Home/GetRides',
{
LineaSelezionata: self.selectedLinea(),
DirezioneSelezionata: $('input[name=radio4]:checked', '.areaselezione').val()
},
function (data) {
debugger;
self.ArrayCorse(data);
});
});
}
lineeVM = new LineeViewModel();
ko.applyBindings(lineeVM);
I have this error when i check to load the 'DropDownCorse':
Uncaught Error: Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.
Can anyone help me to solve this problem???
Thank in advance greetings Donato
You want to use subscribe, not a computed.
self.selectedLinea.subscribe(function (newSelection) {
$.getJSON('/Home/GetRides',
{
LineaSelezionata: newSelection,
DirezioneSelezionata: $('input[name=radio4]:checked', '.areaselezione').val()
},
function (data) {
debugger;
self.ArrayCorse(data);
});
});

How to bind a default value from observable array to dropdown?

I have a dropdown and data binded to it as below
HTML:
<div>
<label>Notice Type</label>
<select id="ntctype" data-bind="options: NoticeType, value: selectedNoticeType, optionsCaption:'Choose...', optionsValue:'NoticeTypeID', optionsText:'NoticeTypeDescription'"></select>
</div>
KO JS:
self.NoticeType = ko.observableArray([]);
self.selectedNoticeType = ko.observable();
$.getJSON("GetNoticeType", null, function (data) {
self.NoticeType(data);
}
);
the NoticeType array looks like this
[{"NoticeTypeID":1,"NoticeTypeDescription":"Close"},{"NoticeTypeID":2,"NoticeTypeDescription":"Open"}]
I would like to set the deafult value as Close after binding.I tried using optionsAfterRender & ko.applybindingstoNode none of them worked.
What would be the clean and neat approach to do this?
As mentioned in the comments you just need to set default value to value binded observable in viewModel
View Model :
function accountViewModel() {
var self = this;
self.NoticeType = ko.observableArray();
self.selectedNoticeType = ko.observable();
self.ajaxcall = function () {
self.NoticeType([{
"NoticeTypeID": 1,
"NoticeTypeDescription": "Close"
}, {
"NoticeTypeID": 2,
"NoticeTypeDescription": "Open"
}]);
self.selectedNoticeType = ko.observable(1);
}
self.ajaxcall();
}
Working fiddle here

Categories

Resources