Reputation: 908
Just got started with knockout and javascript. I'm stuck at setting the object monthData's mPrice value.
function monthData(mYear, mMonth, mSS, mMs, mLimit, mPerItem, mStartingPrice) {
var self = this;
self.mYear= mYear;
self.mMonth = mMonth;
self.mSs = mSS;
self.mMs = mMs;
self.mTotal = mSS + mMs;
self.mLimit = mLimit;
self.mPerItem = mPerItem;
self.mStartingPrice = mStartingPrice;
};
This is were it stops working. if I set self.mPrice = 0 i get all the months printed out atleast.
self.mPrice = ko.computed(function() {
var limit = self.mLimit;
var perItem = self.mPerItem;
var startingPrice = self.mStartingPrice;
var total = self.mTotal;
if (total <= limit) {
return startingPrice;
} else {
var aboveLimit = total - limit;
var extra = aboveLimit * perItem;
return startingPrice + extra;
}
});
}
function statViewModel() {
this.tak = ko.observable(100);
this.styckpris = ko.observable(10);
this.grundpris = ko.observable(500);
var self = this;
// testing with some months
self.allMonths = ko.observableArray([
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris)
]);
}
-Edit: Just after I posted I found a missing paranteses. Now I get it to print out but it says:
function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Va(d);return c}NaN
Html:
<p>Tak: <input data-bind="value: tak" /></p>
<p>Styckpris: <input data-bind="value: styckpris" /></p>
<p>Grundpris: <input data-bind="value: grundpris" /></p>
<table>
<thead>
<tr>
<th>År</th><th>Månad</th><th>SS</th><th>MS</th><th>Total</th><th>Pris</th>
</tr>
</thead>
<tbody data-bind="foreach: allMonths">
<tr>
<td><span data-bind="text: mYear"></span></td>
<td><span data-bind="text: mMonth"></span></td>
<td><span data-bind="text: mSs"></span></td>
<td><span data-bind="text: mMs"></span></td>
<td><span data-bind="text: mTotal"></span></td>
<td><span data-bind="text: mPrice"></span></td>
</tr>
</tbody>
</table>
Upvotes: 1
Views: 3223
Reputation: 908
Edit- this is now working as I wanted
function monthData(mYear, mMonth, mSS, mMs, parent) {
var self = this;
self.mYear = mYear;
self.mMonth = mMonth;
self.mSs = mSS;
self.mMs = mMs;
self.mTotal = mSS + mMs;
self.mPrice = ko.computed(function () {
var limit = parent.tak();
var perItem = parent.styckpris();
var startingPrice = parent.grundpris();
var total = self.mTotal;
if (total <= limit) {
return startingPrice;
} else {
var aboveLimit = total - limit;
var extra = aboveLimit * perItem;
var sum = parseInt(startingPrice) + parseInt(extra);
return sum;
}
});
}
function statViewModel() {
var self = this;
self.tak = ko.observable(100);
self.styckpris = ko.observable(10);
self.grundpris = ko.observable(500);
// testing with some months
self.allMonths = ko.observableArray([
new monthData(2013, 1, 412, 142, self),
new monthData(2013, 2, 112, 642, self),
new monthData(2013, 2, 100, 742, self),
new monthData(2013, 3, 6513, 69, self),
new monthData(2013, 4, 34, 211, self),
new monthData(2013, 5, 123, 435, self),
new monthData(2013, 6, 412, 142, self),
new monthData(2013, 7, 412, 142, self)
]);
}
// Activates knockout.js
ko.applyBindings(new statViewModel());
Upvotes: 2
Reputation: 1398
Please ignore my other answer. I was getting confused between the code in your original question and the answer you posted. And so my explanation was unclear. So here I am going to answer your question, and not using anything from your answer.
The error you were receiving
function d(){if(0<arguments.length){if(!d.equalityComparer||!d.equalityComparer(c,arguments[0]))d.H(),c=arguments[0],d.G();return this}b.r.Va(d);return c}NaN
Can be simplified to
<ko.observable>NaN
And can be read as: "An observable is not a number"
This is an indication that you are trying to perform math operations to an observable.
In your if
statement, you have: if(total <= limit)
. You cannot compare if a number (total
) is less than or equal to (<=
) an observable (limit
). You must get the value of limit by calling it like a function.
Your computed should now look like this:
self.mPrice = ko.computed(function() {
var limit = self.mLimit();
var perItem = self.mPerItem();
var startingPrice = self.mStartingPrice();
var total = self.mTotal;
if (total <= limit) {
return startingPrice;
} else {
var aboveLimit = total - limit;
var extra = aboveLimit * perItem;
return startingPrice + extra;
}
});
Only the first 3 lines need changing - minor changes at that. Nothing else.
Upvotes: 2
Reputation: 1398
Using an observableArray
only 'asks' knockout to 'observe' the array functionality - i.e. push
ing, removing, moving items, etc...
To 'ask' knockout to observe objects within that array, you actually want it to observe an objects particular properties.
So, your monthData
object should declare observable
s instead of regular/primitive properties:
function monthData(mYear, mMonth, mSS, mMs, mLimit, mPerItem, mStartingPrice) {
var self = this;
self.mYear = mYear;
self.mMonth = mMonth;
self.mSs = mSS;
self.mMs = mMs;
self.mTotal = ko.observable( mSS + mMs );
self.mLimit = ko.observable( mLimit );
self.mPerItem = ko.observable( mPerItem );
self.mStartingPrice = ko.observable( mStartingPrice );
...
}
Note, I have only chosen the last 4 to be observable
s because those are the properties you used in your computed
. Now that they are observable
the computed
will know to reevaluate when any of them change.
Also, if you expect self.mTotal
to auto-update (i.e. if you expect self.mSs
or self.mSm
to change), that will need to be a computed
not an observable
.
EDIT:
Don't forget to append any references to these variables with ()
. Your computed should now look like:
self.mPrice = ko.computed(function() {
var limit = self.mLimit();
var perItem = self.mPerItem();
var startingPrice = self.mStartingPrice();
var total = self.mTotal();
if (total <= limit) {
return startingPrice;
} else {
var aboveLimit = total - limit;
var extra = aboveLimit * perItem;
return startingPrice + extra;
}
});
EDIT 2:
Apologies for not reading the question properly.
I didn't realise you were passing in tak
, styckpris
and grundpris
- my brain may have switched off when it saw a different language :p
THE PROBLEM
So what you have done when passing in these to your monthData
constructor is dereference them. You have passed the value behind the observable rather than passing the observable. By passing the value, your monthData
constructor, and thus your mPrice
computed, will have no way of seeing changes to the observable.
THE SOLUTION
Pass the observables into your constructor without dereferencing them.
function monthData(mYear, mMonth, mSS, mMs, mLimit, mPerItem, mStartingPrice) {
var self = this;
self.mYear= mYear;
self.mMonth = mMonth;
self.mSs = mSS;
self.mMs = mMs;
self.mTotal = mSS + mMs;
/* Remember that these are observable! */
self.mLimit = mLimit;
self.mPerItem = mPerItem;
self.mStartingPrice = mStartingPrice;
self.mPrice = ko.computed(function() {
/* So, remember to dereference them! */
var limit = self.mLimit();
var perItem = self.mPerItem();
var startingPrice = self.mStartingPrice();
var total = self.mTotal;
if (total <= limit) {
return startingPrice;
} else {
var aboveLimit = total - limit;
var extra = aboveLimit * perItem;
return startingPrice + extra;
}
});
}
function statViewModel() {
this.tak = ko.observable(100);
this.styckpris = ko.observable(10);
this.grundpris = ko.observable(500);
var self = this;
// testing with some months
self.allMonths = ko.observableArray([
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris),
new monthData(2013, 1, 412, 142, this.tak, this.styckpris, this.grundpris)
]);
}
Upvotes: 3