Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jquery mobile style does not apply in second time navigation to the details page

When I am navigate to details page to second time,page becomes naked,all styles vanish from the page,I could figure out the reason, example http://jsfiddle.net/Hpyca/24/

Html

<div data-role="page" id="dashBoardPage" data-bind="with: dashboardData">
   <button type="button" data-bind="click: goToList">DashBoard!</button>
</div>
<div data-role="page" id="firstPage" data-bind="with: hospitalList">
   <div>
      <div id="listViewDiv">
         <ul data-role="listview" data-bind="foreach: hospitals">
            <li data-bind="click: $parent.selectHospital">
               <h2>Hospital Id:<span data-bind="text:id"></span></h2>
               <p>Name <span data-bind="text:name"></span></p>
            </li>
         </ul>
      </div>
   </div>
</div>
<div data-role="page" id="detailsView" data-bind="with: hospitalList.selectedHospital">
   <a href="#firstPage">Back</a>
   <a href="#dashBoardPage">Home</a>
   <div>
      <div data-role="tabs" id="tabs">
         <div data-role="navbar">
            <ul>
               <li><a href="#one" data-ajax="false">Info</a></li>
               <li><a href="#two" data-ajax="false">Details</a></li>
            </ul>
         </div>
         <div id="one" class="ui-body-d ui-content">
            <h2>Hospital Id : <span data-bind="text:id"></span></h2>
         </div>
         <div id="two">
            <h2>Id : <span data-bind="text:id"></span></h2>
            <input data-mini="true" tabindex="5" data-bind="value: name"
               id="name"/>
         </div>
      </div>
   </div>
</div>

js

function NavigationService(){
    var self = this;

    self.navigateTo = function(pageId){
        $.mobile.changePage($('#' + pageId));
    };
}
//You need to determine if you want to handle dependencies using requirejs or just global variables.
var navigationService = new NavigationService();

function HospitalViewModel(data){
    var self = this;
    self.id = data.id;
    self.name = ko.observable(data.name);
}

function DashboardViewModel(data){
    var self = this;

    self.goToList = function(){
        navigationService.navigateTo('firstPage');
    };
}

function HospitalListViewModel(data){
    var self = this;

    self.hospitals = data;
    self.selectedHospital = ko.observable();

    self.selectHospital = function(hospital){
        self.selectedHospital(hospital);
        navigationService.navigateTo('detailsView');
    };
}

function PageViewModel(){
    var self = this;

    //This list should be retrieved from a service of some kind
    var allHospitals = [
        {"id":"001","name":"Hospital1","location":"SL"},
        {"id":"002","name":"Hospital2","location":"SL"}
    ].map(function(hospital){return new HospitalViewModel(hospital);});

    self.hospitalList = new HospitalListViewModel(allHospitals);
    self.dashboardData = new DashboardViewModel();
}

ko.applyBindings(new PageViewModel());

To reproduce the issue , Click(DashBoard) --> Click(ListElement) --> Click(Back,Home) --> Click(again list element --> go to details page),now you can see the naked UI,

like image 356
ExCode Avatar asked Apr 25 '14 02:04

ExCode


2 Answers

The problem is coming from the KnockoutJS "with:" statement.

My guess is that the "with:" turns a weird property "visible" or "display" to false when the ko.observable is empty, and then Jquery (mobile) trying to use the property to apply style, fails to find the DOM item with its selector. The crazy thing being that I did not find any source documenting the issue?

I experimented similar problem with some Jquery plugins before (datepicker, masked inputs...), the solution I found was re-apply Jquery plugin after binding the observable.

Unfortunately, this "hack" is not useful in your case as Jquery Mobile is not manually applied via JavaScript. I looked for some way "to refresh" Jquery Mobile but no result.

So I came up with a solution by removing "with:" statement, calling the full property name and binding an empty "hospital" in the observable to prevent null reference exception.

JsFiddle

<span data-bind="text:hospitalList.selectedHospital().id"></span>

self.selectedHospital = ko.observable({id:"",name:"",location:""});

This solution is far from ideal, and not really scalable. But, the other way would be inspecting the code of both libraries to identify the "conflict".

Hope it helps!

like image 149
Yooz Avatar answered Nov 15 '22 17:11

Yooz


Found the answer for you, and I've updated your original fiddle - it is now working as intended. The only change made was to your NavigationService as follows:

function NavigationService() {
    var self = this;

    self.navigateTo = function (pageId) {
        $.mobile.changePage($('#' + pageId));
        $('#detailsView').trigger('create'); // add this line
    };
}

There are a few other questions here on SO that address this:

  • Forcing jQuery Mobile to re-evaluate styles/theme on dynamically inserted content
  • jQuery Mobile does not apply styles after dynamically adding content
like image 2
rwisch45 Avatar answered Nov 15 '22 18:11

rwisch45