Get Object Out Of Observable Array
Solution 1:
You just need to change if(currentViewModel.availableReports()[i].id ...
to if(currentViewModel.availableReports()[i].id() ...
because after mapping id
will become an observable, i.e. function.
Updated code:
currentViewModel = ko.mapping.fromJS(viewModel);
currentViewModel.getReport = function(reportId) {
for (var i = 0; i < currentViewModel.availableReports().length; i++) {
if (currentViewModel.availableReports()[i].id() == reportId) {
var m = currentViewModel.availableReports()[i];
return currentViewModel.availableReports()[i];
}
}
}
Demo - Fiddle.
Solution 2:
I'll repeat the solution from @NikolayErmakov's answer here, but want to add two things to get a more complete answer. You end with:
...
m
remains undefined and the function returnsundefined
.What am I missing here?
You're missing two things:
- The
var m
bit of the first statement inside theif
is hoisted to the top of the current scope (the top of the function). This is why the debugger can tell you whatm
is, even if you never reach the line of code it's on. - If a function invocation reaches the end of a function (as is the case for you, since you never go inside the
if
) without seeing an explicitreturn
statement, it will returnundefined
.
To better understand this, you should interpret your function like this:
currentViewModel.getReport = function(reportId) {
var m;
for (var i = 0; i < currentViewModel.availableReports().length; i++) {
if (currentViewModel.availableReports()[i].id == reportId) {
m = currentViewModel.availableReports()[i];
return currentViewModel.availableReports()[i];
}
}
return undefined;
}
Some people (e.g. Douglas Crockford) do recommend placing var
statements at the top of a function, though it's a matter of style to some degree. I don't think many people explicitly return undefined
at the end of a function, though in your case I might be explicit about that scenario and return null
(or throw an Error even).
As promised, I'll repeat the actual solution, as I concur with the other answer:
- you need to invoke
id
as a function to get its value (because themapping
plugin will map toobservable()
s.
In addition:
- I'd retrieve the array only once
- I'd suggest using
===
instead of==
Here's my v0.5 version:
currentViewModel.getReport = function(reportId) {
var m = null, reports = currentViewModel.availableReports();
for (var i = 0; i < reports.length; i++) {
if (reports[i].id() === reportId) {
m = reports[i];
return m;
}
}
return m;
}
But I'd optimize it to this v1.0:
currentViewModel.getReport = function(reportId) {
var reports = currentViewModel.availableReports();
for (var i = 0; i < reports.length; i++) {
if (reports[i].id() === reportId) {
return reports[i];
}
}
return null;
}
For completeness, here's another version that utilizes filter
on arrays:
currentViewModel.getReport = function(reportId) {
var reports = currentViewModel.availableReports().filter(function(r) { return r.id() === reportId; });
return reports.length >= 1 ? reports[0] : null;
}
Post a Comment for "Get Object Out Of Observable Array"