I have a setup for a test app which includes require.js, jQuery, jQueryMobile (jqm), knockout and sammy
require.js loads in jqm, knockout and sammy
on the app main page i use sammy to load in knockout viewModels. these viewModels the load in the templates..
so to show the code...
require page:
require.config({
jquery: 'vendor/jqm/jquery_1.7_min',
jqm: 'vendor/jqm/jquery.mobile-1.1.0',
knockout: 'vendor/knockout/knockout-2.2.0',
sammy : 'vendor/sammy/sammy',
text: 'vendor/require/text',
views: '../views',
templates: '../templates'
}
});
define(['app','jqm-config'], function(app) {
$(document).ready(function() {
console.log("DOM IS READY");
});
});
app.js
define(['jquery','knockout', 'sammy','views/home/home', 'views/products/products', 'jqm'],
function($, ko, sammy, appViewModel, productsViewModel) {
var self = this;
self.goHome = function() {
ko.applyBindings(new appViewModel());
};
self.goProducts = function() {
ko.applyBindings(new productsViewModel());
};
Sammy(function() {
this.get('#home', function() {
self.goHome();
});
this.get('#products', function() {
self.goProducts();
});
this.get('', function() {
self.goHome();
});
}).run();
});
products page
define(['jquery', 'knockout','text!templates/test2.html', 'jqm'],
function($, ko, productsViewTemplate){
function ProductType(id, name) {
var self = this;
self.id = id;
self.name = name;
}
return function productsViewModel() {
$('body').append(productsViewTemplate);
var self = this;
self.products = ko.observableArray();
var jqxhr = $.getJSON("data/product.json")
.success(function(data, status, xhr) {
self.products.removeAll();
$.each(data.data.productTypeList, function(i,item){
self.products.push(new ProductType(i, item.longName));
})
})
.error(function() { alert("error"); })
.complete(function() {
$.mobile.changePage( '#products', { transition: "pop"});
});
}
});
products html (text2.html)
<div data-role="page" data-theme="c" class="ui-page" id="products">
<div data-role="header" data-position="fixed">
<h1>Products</h1>
<a href="#home" data-icon="home" data-iconpos="notext" data-direction="reverse">Home</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true" data-bind="foreach: products" >
<li>
<a data-bind="attr:{href:'#products/list/' + id}, text: name"></a>
</li>
</ul>
</div>
There are a couple of problems
is sammy supposed to be loaded in that order because every now and again when i refresh it throws an error that sammy or jquery is not defined due too slow loading i am guessing
on the products page if someone goes it from the homepage it loads ok because the jQueryMobile changePage has been called but if a user then refreshes that page the list that has come from the JSON looses all its styling..
I think this is due to the way I render the page from the template and then have to make the list but i cant think of another way of doing it.
so i was thinking (prob not best solution) but is there a way to force a pageChange on a refresh? or has anyone got a better solution?
3.
Is this the best way to call in an external template / is there a better way to append the template to the body. I really think the time its taking to do that is what causing the styling issues and also when i add in the next level of products its starts rendering them on this page before moving to the next..
I am struggling to find the best way to load in external templates with knockout and requirejs. I want to keep the templates in HTML so that others in the team can edit it easily enough and to give a structure.
this demo can be seen here
http://demo.stg.brightonconsulting.net.au/templates/tests/knockoutJQMProducts/
Really appreciate any help
Looking at your demo, I can suggest a few things to try.
main.js
remove the dependency onjqm-config
and add it toapp.js
. That way, you will always be guaranteed to have set up your jquery mobile configuration before anything inapp.js
is run.ko.applyBindings()
call is wrapped in a.ready()
construct.Even with all those items fixed, I'm not sure that the way you're going about things will work. You may be better off loading all the HTML up front and binding all the pages to one parent viewmodel with subviewmodels.