KnockoutJs computed array not calculated correctly - javascript

The code is as follows: EmployeeModel is the viewModel and the problem is that when I change an item's property - deletedFlag in employees (obs array), deletedItems is not updated.
How can i fix this?
function Employee(data) {
this.employeid = ko.observable(data.employeid);
this.name = ko.observable(data.name);
this.isactive = ko.observable(data.isactive);
this.deletedFlag = ko.observable(false);
}
var EmployeeModel = function () {
var self = this;
self.employees = ko.observableArray([]);
self.deletedItems = ko.computed(function () {
return ko.utils.arrayFilter(self.employees(), function (item) {
return item.deletedFlag == true;
});
}, this);
}
EDIT: and the following code marks one item from the array for deletion
self.removeEmployee = function (employee) {
employee.deletedFlag(true);
};

The property deletedFlag is an observable, therefore you need to retrieve its current value by invoking it as a function (you cannot compare it directly to any value):
self.deletedItems = ko.computed(function () {
return ko.utils.arrayFilter(self.employees(), function (item) {
return item.deletedFlag() == true; // <===
});
}, this);

Related

How to return a list of available options in a select element in Protractor?

I am trying to retrieve all the options available in select element using Protractor. I am having trouble figuring out how to do this because I'm a JavaScript beginner and therefore am having trouble determining how to return the array and not a promise.
I've tried this:
getOptions = function () {
var self = this;
var availableOptions = [];
return this.selector.click().then(function () {
self.selectorOptions.then(function (options) {
options.forEach(function (option) {
option.getAttribute("value").then(function (value) {
availableOptions.push(value);
});
});
});
}).then(function () {
return availableOptions;
});
};
This returns a promise and not the array which I want. I also tried this:
getOptions = function () {
var self = this;
var availableOptions = [];
this.selector.click().then(function () {
self.cloudletTypeOptions.then(function (options) {
options.forEach(function (option) {
option.getAttribute("value").then(function (value) {
availableOptions.push(value);
});
});
});
});
return availableOptions;
};
When I do this and call the method from a test and try to print the result, it is 'undefined'. What do I need to do to ensure that the return value is defined and is an array? Barring that, how do I force the promise to resolve?
From what I understand, you are looking for map():
Apply a map function to each element within the ElementArrayFinder.
The callback receives the ElementFinder as the first argument and the
index as a second arg.
getOptions = function () {
var self = this;
return this.selector.click().then(function () {
return self.selectorOptions.map(function (option) {
return option.getAttribute("value").then(function (value) {
return value;
});
});
});
};

How to bind array data from Json to knockout observable array

Please find below code from .cshtml page
Below code gives databind for observables but not for observable array.
var getLocationDetails = function (locationCode)
{
return $.getJSON('#Url.Action("MasterDetails")',
{ locationcode: locationCode });
};
var setModelData = function (self, locationDetails)
{
self.UneditedLocationDetails = _(locationDetails).cloneDeep();
for (var key in locationDetails)
{
locationDetails[key] = ko.observable(locationDetails[key]);
}
function LocationModifyViewModel()
{
var self = this;
initAjax(self);
var initModel = setModelData.bind(self);
var initModel = setModelData.bind(self);
self.TextboxLocationcode.subscribe(function (val)
{
getLocationDetails(val).success(function (locationDetails) {
setModelData(self, locationDetails);
});
In the above code databinded to locationDetails, where I want to add observablearray values to locationDetails or else if possible to new variable.

KnockoutJS passing ko.computed values to a function

I have a working knockout js script, myValues is an array result of a ko.computed, then I pass it down to myValues2 which calls a myFunction to make each object in that array as "observable". This works but I wanted to call myFunction in self.myValues so that I wouldn't have to create another observableArray myValues2. Can you help me combine the script of myValues and myValues2 so that I can finally delete self.myValues2. Here is my code:
var myFunction = function (id, name, amount, automatic) {
var self = this;
self.Id = ko.observable(id);
self.Name = ko.observable(name);
self.Amount = ko.observable(amount);
self.Automatic = ko.observable(automatic);
};
self.myValues = ko.computed(function () {
return ko.utils.arrayFilter(self.completeList(), function (ded) {
return ded.automatic() == true;
});
});
self.myValues2 = ko.observableArray();
self.myValues2(ko.utils.arrayMap(self.myValues(), function (dd) {
return new myFunction(dd.id(), dd.name(), dd.amount(), dd.automatic());
}));
self.completeList()
how defined this array?
Because you began to filter this list by automatic field and then to fill other list. Strange order.
return ded.automatic() == true;

Writing an escaped/unescaped Observable in Knockout

I have an issue where I want to store everything as quoted strings and display everything unquoted while in the form. My first solution was to just create two extra bindingHandlers to do this one for value and one for text.
ko.bindingHandlers.escapedValue = {
init : function (element, valueAccessor, allBindingsAccessor) {
var $element = $(element),
contentObservable = valueAccessor(),
currentTxt = ko.utils.unwrapObservable(contentObservable);
if (currentTxt) {
$element.val(unescape(currentTxt));
}
$element.change(function (e) {
contentObservable(escape($element.val()));
});
}
};
ko.bindingHandlers.escapedText = {
init : function (element, valueAccessor, allBindingsAccessor) {
var $element = $(element),
contentObservable = valueAccessor(),
currentTxt = ko.utils.unwrapObservable(contentObservable);
if (currentTxt) {
$element.text(unescape(currentTxt));
}
contentObservable.subscribe(function (newValue) {
$element.text(unescape(newValue));
});
}
};
However that gave me two issues 1) I do not get live updating anymore after key down 2) When I do some validation on the values for example character length it checks the length of the quoted string.
How can I write something like a ko.escapedObservable() or ko.subscribable.fn.escaped()
I have gotten closer but cant seem to get the saving correct. So now it displays properly and does the comparison properly but when I goto save it the values are still unescped
ko.escapedObservable = function (initialValue) {
var observableVal = ko.observable(initialValue),
result = ko.computed({
read: function () {
return unescape(observableVal());
},
write: function (newValue) {
return observableVal(escape(newValue));
}
});
this.toJSON = function () {
return escape(observableVal());
};
return result;
};
====EDIT====
Solution using two observables
// Escape and Unescape a text value
ko.escapedObservable = function (initialValue) {
var observableVal = ko.observable(initialValue),
result = ko.computed({
read: function () {
return observableVal();
},
write: function (newValue) {
observableVal(newValue);
}
});
result.unescaped = ko.computed({
read: function () {
return unescape(observableVal());
},
write: function (newValue) {
observableVal(escape(newValue));
}
});
return result;
};
ko.escapedObservable = function (initialValue) {
var observableVal = ko.observable(initialValue),
result = ko.computed({
read: function () {
return observableVal();
},
write: function (newValue) {
observableVal(newValue);
}
});
result.unescaped = ko.computed({
read: function () {
return unescape(observableVal());
},
write: function (newValue) {
observableVal(escape(newValue));
}
});
return result;
};
I'm having trouble figuring out exactly what you are asking. However, I believe you really just need a computed observable: [Example]
function viewModel() {
this.test = ko.observable('\"Something\"');
this.escapedTest = ko.computed(function () {
return escape(this.test());
}, this);
this.unescapedTest = ko.computed(function () {
return unescape(this.escapedTest());
}, this);
}

knockout variable not defined - scoping issue?

I have the following code:
var ObjectViewModel = function (testObject) {
//debugger;
var self = this;
self.id = testSet.id;
self.details = testOject.details;
self.children = ko.observableArray(testObject.children);
self.childCount = ko.computed(function() {
return self.children().length;
});
self.addObject = function () {
//debugger;
// Pending UI
// Call API here
// On success, complete
self.children.push(dummyObject);
self.childToAdd("");
}.bind(self);
}
/ etc
However in childCount, this.children() is undefined. I'm trying to let the view show the length of the children array in real-time, so as the user adds/removes items, the count is updated. Any idea why this isn't working?
You can pass what the value of this should be when the function is executed to the computed function with the last parameter:
this.childCount = ko.computed(function() {
return this.children().length;
}, this);
You could also store a reference to this outside of the computed:
var self = this;
this.childCount = ko.computed(function () {
return self.children().length;
});

Categories

Resources