While working on an ongoing learning project, I noticed that I require a writeable computed function to solve a problem I'm facing. Here's the skinny: I'm trying to 1) drop a user-specified number of assignments scores 2) of a user specified type from a gradebook.
The user inputs the value above, then click a button, dropLowestScores
. The code then adds the lowest scores to an array called 'lowest', which exists on each student
object.
Then, observable mean
s on each student are updated based on new values, dropping the lowest ones.
My problem comes to life when I try to drop. I'm not confident that my writeable computed is structured correctly, but I'm not sure what's wrong either. I noticed that that properties 'n' and workType
are correctly given in my read
function, but in my write
, they are not as desired. In read
, for example, workType
returns default value, homework
, but in my write
function, it returns [object Object]
.
Responses that can clarify what my problem is and give me a strategy for correctly scripting a writeable computed would be appreciated.
Relevant JS and HTML snippets follow.
JSBin: Full Project
this.dropLowestScores = ko.computed({
// read the parameters necessary to write values to property 'lowest'
read: function() {
// user sets value of 'n' in the page via ko 'options'
var n = _this.n().n;
// user selects 'workType' from list of ko options
var workType = _this.workType().workType;
console.log("workType:" + workType);
return n,workType;
},
// now use current parameter values to set new values to 'lowest' arrays
write: function(n,workType) {
//this.n = n;
//this.workType = workType;
// 'lowest' exists as a property for each student,
// ergo, I loop through each student
ko.utils.arrayForEach(_this.students(), function(student){
var i = _this.students.indexOf(student);
console.log("_this.assignments: " + _this.assignments()[i].workType().workType);
console.log("this.workType: " + this.workType);
console.log(_this.assignments()[i].workType().workType == this.workType);
// if the current assignment is the same as the user-specified assignment,
//add the score for that assignment to array 'tmp'; then set lowest = tmp
if(_this.assignments()[i].workType().workType == this.workType){
var tmp = student.scores().sort(_this.comparator).slice(0,this.n);
console.log(tmp.length);
student.lowest(tmp);
}
});
}
});
<button data-bind="click: dropLowestScores">Drop Lowest Scores</button>
Currently, I just have the above function bound to a butten. Ideally, this is how I'd leave it. Other properties referenced, such as n
, workType
, and mean
are input in a table.
I feel silly now, but it turns out I was on the right track; indeed, the solution was trivially simple. In the read
function, I just needed to define properties in the following way:this.variable = ...
as opposed to var variable = ...
.
this.dropLowestScores = ko.computed({
// read the parameters necessary to write values to property 'lowest'
read: function() {
// user sets value of 'n' in the page via ko 'options'
this.n = _this.n().n;
// user selects 'workType' from list of ko options
this.workType = _this.workType().workType;
console.log("workType:" + workType);
return n,workType;
},
...