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 = koputed(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>
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.puted(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>
Share
Improve this question
edited May 17, 2013 at 14:02
Ashkan Hovold
asked May 16, 2013 at 11:24
Ashkan HovoldAshkan Hovold
9062 gold badges15 silver badges31 bronze badges
3
- Please post your html code, you are also missing a set of parentheses there... – nemesv Commented May 16, 2013 at 11:58
- The problem isn't with the html but sure – Ashkan Hovold Commented May 16, 2013 at 11:59
- Please see my 2nd answer. The 1st answer, I admit, was a bit confusing. – Sethi Commented May 17, 2013 at 11:23
3 Answers
Reset to default 3Using 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 puted
. Now that they are observable
the puted
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 puted
not an observable
.
EDIT:
Don't forget to append any references to these variables with ()
. Your puted should now look like:
self.mPrice = ko.puted(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
puted, 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.puted(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)
]);
}
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 pare 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 puted should now look like this:
self.mPrice = ko.puted(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.
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.puted(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());