I have the following setup on my site. It is working fantastically on any standard browser and any normal mobile browser:
Model:
function SearchTerm(data) {
this.Term = ko.observable(data.Term);
this.Stamp = ko.observable(data.Stamp);
}
ViewModel:
function HistoryViewModel() {
//Data
var self = this;
self.searchTerms= ko.observableArray([]);
// Load history from server
$.ajax({
type: "GET",
url: "/api/history/",
data: null,
success: function (msg) {
var terms = $.map(msg, function (item) { return new SearchTerm(item) });
self.searchTerms(terms);
},
error: function (xhr, ajaxOptions, thrownError) {
// Error Handling
}
});
}
View:
<div class="title">
Search History
<div class="closeBtn"></div>
</div>
<div id="historySection">
<ul class="searches" data-bind="foreach: searchTerms">
<li class="historyItem">
<div class="timestamp"><span data-bind="'text': Stamp"></span></div>
<span data-bind="'text': Term"></span>
</li>
</ul>
<a class="loadMore">Load 10 More Searches »</a>
</div>
All of this works perfectly on everything I test, with one major exception: The WebView control for Android. Whenever I run this page there, I get the following exception:
Uncaught Error: Unable to parse bindings.
Message: ReferenceError: Stamp is not defined;
Bindings value: 'text': Stamp at {url}/Scripts/libs/knockout-2.2.1.js:5
I'm at my wit's end. I've tried every possible combination of data-bind syntax (as you can see I've tried the single quotes too, as I'd seen a post related to that at some point). My only guess now is that this might be related to my order of scripts. I do currently reference knockout before I reference jquery - could this be the issue? I hadn't seen this as an issue anywhere else, but at this point, I'm willing to try anything.
Update:
All of my other knockout binding viewModels and bindings are working fine on Android, but none of them occur on page load. So that led me to look at changing the ajax to a method and trying to delay it's calling. So I implemented the following addition to my viewmodel:
//Operations
self.loadRecent = function () {
// Load search history
$.ajax({
type: "GET",
url: "/api/history/",
data: null,
success: function (msg) {
var terms = $.map(msg, function (item) { return new History(item) });
self.history(terms);
},
error: function (xhr, ajaxOptions, thrownError) {
//Error handling
}
});
In my page, here is what the initial binding looks like - it occurs at the bottom of the page:
var history = new HistoryViewModel();
ko.applyBindings(history, $("#historySection")[0]);
//Call page event handlers
$(window).load(function () {
// Load in our search history
history.loadRecent();
});
Unfortunately, same error as before. However, this is where things get really interesting. Even when I comment out the call to the loadRecent operation, I still get the error! To me, this means, for some reason, for this model only, the foreach is still trying to iterate, even though nothing exists. Do my assumptions sound correct? Anyone see anything I'm blatently missing here that would cause this issue? None of my other viewModels and views are having this issue. I have 2 others I'm binding to and they both have foreach's in them and do not seem to experience this issue.
UPDATED 2013.05.20 I updated some of the code throughout to reflect some function/object renaming I did, as I started to worry that something was getting out of sorts with me having a variable named history with a function named history (silly, I know, but I'm desparate).
I also wanted to post an additional finding. I decided to go ahead and try removing the code for loading the history completely from any loading or ready event. Rather, I was able to separate out this data load into a button click. Here is what the button click handler looks like:
$(".menuButton").on("click", "", function () {
history.searchTerms([]);
history.loadRecent();
});
Fun fact when I do this though, in Android-only. I still get an error on load, in the bindings:
Uncaught Error: Unable to parse bindings.
Message: ReferenceError: searchTerms is not defined;
Bindings value: foreach: searchTerms at {url}/Scripts/libs/knockout-2.2.1.js:5
Another interesting tidbit - if I were to remove the html from the view altogether, meaning there are no bindings, yet still leave the code for the SearchTerm model and the HistoryViewModel, I still get an error from the WebView in Android, when the button is clicked:
Uncaught TypeError: Object #<History> has no method 'searchTerms' at {url}:681
Sorry for so much posting, but I'm desperate to figure out what's wrong with this.