knockout observable array bounded listview doesnt get rendered in JQM - jquery-mobile

JQM listview get populated as with the data with no issue as expected, but i cant get it rendered with JQM styles. could any one can help me with this issue.
I have tried with listview(), listview("refresh"), trigger("create") none of them did work
var ProfessionsModel = function() {
var self = this;
self.professionDetails = ko.observableArray([]);
self.getProfessionDetails=function(){
var rest = new RestService('${pageContext.request.contextPath}/rest/profession/designations');
rest.findAll(function(data) {
$.each(data, function(index, value){
self.professionDetails.push(value);
});
});
};
self.removeProfessionDetails= function(){
self.professionDetails.removeAll();
};
};
var pm = new ProfessionsModel();
$('#profession').live('pagecreate', function(event) {
ko.applyBindings(pm, this);
});
$('#profession').live('pagebeforeshow', function(event) {
pm.removeProfessionDetails();
});
$('#profession').live('pageshow', function(event) {
pm.getProfessionDetails();
$('#profession').find("ul").listview();
$('#profession').find("ul").listview("refresh");
});

You are doing it in a wrong moment. You want believe how jQM is picky about a right moment.
var ProfessionsModel = function() {
var self = this;
self.professionDetails = ko.observableArray([]);
self.getProfessionDetails=function(){
var rest = new RestService('${pageContext.request.contextPath}/rest/profession/designations');
rest.findAll(function(data) {
$.each(data, function(index, value){
self.professionDetails.push(value);
});
$('#profession').find("ul").listview();
$('#profession').find("ul").listview("refresh");
});
};
self.removeProfessionDetails= function(){
self.professionDetails.removeAll();
};
};
jQM trigger refresh will brake if not executed after content has been appended, hence refresh after $.each part.

Related

why the function in side of function wont get called?

i have the following reactjs code to generate two dropdown list where the ddlproducts gets loaded by ddlCategories selection. but when i called the function getDataById() and tried to print the ajax populated array data2 to alert(), there was no alert() there were two alerts none of the alerts were prompted. it shown this error message on the IE console,
execution did not reached the function getDataById() 'cus the alert() in that function even didn't execute
SCRIPT438: Object doesn't support property or method 'getDataById'
correction: once the calling of this.props.getDataById() was changed to this.getDataById() it worked
but how do populate the ddlProducts dropdown. how do i access tag of the ddlProducts and then add the options to it?
here is the code:
var gdata=[];
var trStyle = {
'color': 'black',
'border-style' :'solid',
'margin-left':'20%'
};
var HCOMP = React.createClass({
getInitialState:function(){
return{data1:[], data2:[], isMounted:false, selectedValue:0}
},
componentDidMount:function(){
this.getData();
this.setState({isMounted:true})
},
ddlProdCatsChanegeEvent: function(e) {
if (this.state.isMounted)
{
var newV = ReactDOM.findDOMNode(this.refs.refProdCats).value;
var seleValue = newV;
this.setState({selectedValue:newV}, function(){
this.getDataById(this.state.selectedValue);
alert(this.state.data2);
});
}
},
render: function() {
var prodCats = this.state.data1.map(function(ele, index){// <PRODCATSOPTION optValue={ele.ProductCategoryID} optText={ele.Name} />
return <option value={ele.ProductCategoryID} data-key={index}>{ele.Name}</option>
});
prodCats.unshift(<option value={''}>{'---- select category ------'}</option>)
return (<div>Prodcut Category:<br /><select id="ddlCategories" ref="refProdCats" onChange={this.ddlProdCatsChanegeEvent}>{prodCats}</select><br />
Products:<br /><select id="ddlPorducts" ref="refProds"></select><br /></div>
)
},
getDataById:function(catId){
var x = catId;
alert('rec id:'+x);
$.ajax({
url:'http://localhost:53721//Home/GetProductCats?id='+ x,
method:'GET',
success:function(d1){
this.setState({data2:d1});
}.bind(this),
error:function(){
alert('ERROR');
}.bind(this)
})
},
getData:function(){
//ajax here
$.ajax({
url:'http://localhost:53721//Home/GetProductCats',
method:'GET',
success:function(d1){
this.setState({data1:d1});
}.bind(this),
error:function(){
alert('ERROR');
}.bind(this)
})
}
});
var PRODOPTIONS = React.createClass({
render:function(){
return(<option value={this.props.optValue}>{this.props.optText}</option> )
}
});
var PRODCATSOPTION = React.createClass({
render:function(){
return(<option value={this.props.optValue}>{this.props.optText}</option> )
}
});
ReactDOM.render( <HCOMP/>, document.getElementById('d1') );
Try updating ddlProdCatsChanegeEvent to ddlPropCatsChangeEvent.

JQueryMobile: pagecontainershow on a particular page not working

JQueryMobile 1.4 has deprecated the pageshow event and instead recommends using pagecontainershow; however, while I'm able to get the pagecontainershow event at a document level, I can't bind a function to a particular page.
<div id="page1" data-role="page">
...
<script>
$( "#page1" ).on( "pagecontainershow", function( event, ui ) {
console.log("page1 pagecontainershow");
} );
</script>
</div>
Demonstration: http://jsbin.com/IFolanOW/22/edit?html,console,output
I also considered using the alternative form of the jQuery "on" function where we use a selector, but that would need to be a parent of the page div, and that might include other pages, so that doesn't work.
As a workaround, I've done this, but it is very inefficient:
function registerOnPageShow(pageId, func) {
var strippedPageId = pageId.replace("#", "");
var e = "pagecontainershow." + strippedPageId;
// TODO why isn't it working to use $(pageId) instead of $(document)?
$( document ).off(e).on(e, null, {page: strippedPageId, f: func}, function(e, ui) {
if ($(":mobile-pagecontainer").pagecontainer("getActivePage")[0].id == e.data.page) {
e.data.f(e, ui);
}
});
}
You can get the page ID like this.
$(document).on('pagecontainershow', function(e, ui) {
var pageId = $('body').pagecontainer('getActivePage').prop('id');
});
There is currently no way to have a show/hide event on a specific page.
Here is what I'm using (jqmobile >1.4):
$(document).on("pagecontainershow", function () {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
var activePageId = activePage[0].id;
switch (activePageId) {
case 'loginPage':
...
break;
case 'homePage':
...
break;
case 'groupPage':
...
break;
default:
}
});
$(document).on("pagecontainershow", function(event, ui) {
var pageId = $('body').pagecontainer('getActivePage').prop('id'),
showFunc = pageId+'_show';
if (typeof MobileSite[showFunc] == 'function') {
MobileSite[showFunc]();
}
});
MobileSite is contained in an external .js file with all the show() functions.
$(document).on("pagecontainerbeforeshow", function (event, ui) {
if (typeof ui.toPage == "object") {
var crrentPage = ui.toPage.attr("id")
}
});
and you must use this code before calling Index.js !!

Why do I have an extra empty page when I add jquery mobile 1.3.2?

When I load the jquery mobile I have an extra empty page that messes with the app (changes to a white page) when I use the options tag in html, for example.
But only when I have data-native-menu="false"
This is the extra page:
<div data-role="page" data-url="/" tabindex="0" class="ui-page ui-body-c" style="min-height: 629px;">
Someone can explain to me how to use the jquery mobile without the extra page?
Code:
main:
require(['app', 'jquery', 'backbone', './router'], function (App, $, Backbone, Router) {
'use strict';
$( document ).on( "mobileinit",
// Set up the "mobileinit" handler before requiring jQuery Mobile's module
function() {
// Prevents all anchor click handling including the addition of active button state and alternate link bluring.
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
// $.mobile.selectmenu.prototype.options.nativeMenu = false;
$.mobile.ajaxEnabled = false;
$.mobile.pushStateEnabled = false;
$('div[data-role="page"]').live('pagehide', function (event, ui) {
$(event.currentTarget).remove();
});
}
)
require( ['jquery-mobile-bower'], function() {
// Instantiates a new Backbone.js Mobile Router
var router = new Router();
Backbone.history.start();
});
});
Router:
define([ "jquery", "backbone", './views/views'], function($, Backbone, views) {
var changeView = function(view){
view.render([{}]);
$(view.el).attr('data-role', 'page');
$('body').append(view.el)
var el = view.el;
$.mobile.changePage($(view.el));
}
// Extends Backbone.Router
var CategoryRouter = Backbone.Router.extend( {
// The Router constructor
initialize: function() {
// Tells Backbone to start watching for hashchange events
$('.back').live('click', function(event) {
window.history.back();
return false;
});
},
// Backbone.js Routes
routes: {
"": "index",
"aa": "aa"
},
// Home method
index: function(){
var view = new views.Index();
changeView(view);
view.on('changePage', function(pageName){
})
},
aa: function(){
var view = new views.A();
changeView(view);
}
} );
// Returns the Router class
return CategoryRouter;
} );
Thanks

events not firing when creating single instance of a view, but works when mutliple instance are created

I'm a complete newbie to Backbone and am trying to get my head round few things. Im trying to build something using jQuery mobile and Backbone. Please find my code below
var WelcomePage = Backbone.View.extend({
initialize:function () {
this.template = _.template($("#welcome_template").html());
},
render:function (eventName) {
$(this.el).html(this.template());
return this;
},
events:{
"click .btn_continue" : function(){
appRouter.navigate('login',{trigger: true});
}
}
});
var Login = Backbone.View.extend({
initialize:function () {
this.template = _.template($("#login_template").html());
},
render:function (eventName) {
$(this.el).html(this.template());
return this;
},
events:{
"click .btn_login" : function(){
appRouter.navigate('dashboard',{trigger: true});
}
}
});
var Dashboard = Backbone.View.extend({
initialize:function () {
this.template = _.template($("#dashboard_template").html());
},
render:function (eventName) {
$(this.el).html(this.template());
return this;
},
events:{
"click .btn_loadImages" : function(){
console.log('load Images');
}
}
});
var Router = Backbone.Router.extend({
routes:{
"":"welcome",
"login":"login",
"dashboard":"dashboard",
},
initialize:function () {
},
welcome:function () {
this.changePage(new WelcomePage());
},
login:function () {
this.changePage(new Login());
},
dashboard:function(){
this.changePage(new Dashboard());
},
changePage:function (page) {
$(page.el).attr('data-role', 'page');
page.render();
$('body').append($(page.el));
$.mobile.changePage($(page.el), {changeHash:false, transition: 'slide'});
}
});
var appRouter = new Router();
Backbone.history.start();
Now while I go back and forth through the screens using the BACK key the events fire OK using the code above. Then I tried replacing the code for the Router with the code below
var Router = Backbone.Router.extend({
routes:{
"":"welcome",
"login":"login",
"dashboard":"dashboard",
},
initialize:function () {
},
welcome:function () {
this.changePage(v_WelcomePage);
},
login:function () {
this.changePage(v_Login);
},
dashboard:function(){
this.changePage(v_Dashboard);
},
changePage:function (page) {
$(page.el).attr('data-role', 'page');
page.render();
$('body').append($(page.el));
$.mobile.changePage($(page.el), {changeHash:false, transition: 'slide'});
}
});
var v_WelcomePage = new WelcomePage();
var v_Login = new Login();
var v_Dashboard = new Dashboard();
var appRouter = new Router();
Backbone.history.start();
I noticed when I go back to the previous screens the events stop firing. Instead of creating the instance of the view in the action of the router I have created it outside and call it each time.I hope im making some sense.
Any advice much appreciated.
Events are hooked up using jQuery when the view is instantiated, not rendered (in the Backbone View constructor function). jQuery disconnects those events when the html is removed from the page (probably in $.mobile.changePage).
So, the second time you render the page, the events will not be hooked back up. You could try calling page.delegateEvents() to manually hook up the events again, or you could re-create the view each time.

changing a page in jqm after a fetch - view not displaying backbone

I am trying to change a page and display a view with JQM and backbone.
My home page loads ok but when I try and go to the second page - this is when I have a few questions. the page loads but nothing is showing
so my app has a router
var AppRouter = Backbone.Router.extend({
//define routes and mapping route to the function
routes: {
'': 'showHome', //home view
'home': 'showHome', //home view as well
'products/productList' : 'showProducts',
},
initialize:function () {
// Handle back button throughout the application
$('.back').live('click', function(event) {
window.history.back();
return false;
});
this.firstPage = true;
},
defaultAction: function(actions){
this.showHome();
},
showHome:function(actions){
// will render home view and navigate to homeView
var homeView=new HomeView();
homeView.render();
this.changePage(homeView, 'fade');
},
showProducts:function(){
var productList=new Products();
var self = this;
productList.fetch({
success:function(data) {
self.changePage(new ProductListView({collection:data}));
}
});
},
changePage:function (view, transition) {
//add the attribute 'data-role="page" ' for each view's div
if (transition != "slidefade") {
transition = "pop";
}
view.$el.attr('data-role', 'page');
$('.ui-page').attr('data-role', 'page');
//append to dom
$('body').append(view.$el);
if(!this.init){
$.mobile.changePage($(view.el), {changeHash:false, transition: transition});
}else{
this.init = false;
}
}
});
$(document).ready(function () {
console.log('App Loaded');
app = new AppRouter();
Backbone.history.start();
});
return AppRouter;
here is also my view page for product
var ProductListView = Backbone.View.extend({
template: _.template(productViewTemplate),
initialize: function () {
_.bindAll(this, "render");
this.collection.bind("reset", this.render);
},
render: function () {
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
console.log("here");
});
}
});
return ProductListView;
So from within the homeView I can change the page and that's fine the issue what am i doing wrong on the products view for it not to return a thing.. no errors are returned.
thanks
so I have done some more work and made my show products function
showProducts:function(){
var productList=new Products();
var self = this;
var productListView =new ProductListView({collection:productList});
productList.fetch(self.changePage(productListView));
}
this works when the view is
var ProductListView = Backbone.View.extend({
template: _.template(productViewTemplate),
initialize : function () {
_.bindAll(this, "render");
this.collection.bind("reset", this.render, this);
},
render: function() {
var self = this;
this.collection.each(function(model) {
self.$el.append(self.template(model.toJSON()));
console.log("here");
});
}
});
return ProductListView;
but now jQueryMobile doesnt add on its code so it has no styling..
any suggestions?
Both Backbone.js's router and jQuery Mobile use the hashtag and don't work so well together. There are ways to get them to work but unless you have specific reason to do so I'm not sure its worth it, instead I'd recommend using jQuery-Mobile-router which is a plugin for jQuery mobile, that was created for this very reason (that is to work with Backbone.js). As a bonus the jQuery Mobile Router ties in with the special JQM Page events.

Resources