opitzconsulting / jquery-mobile-angular-adapter

jquery mobile angular adapter
MIT License
517 stars 114 forks source link

When transitions are set to 'none' jqm event handlers are entered in the middle of the $digest cycle #153

Closed jupiterplanet closed 11 years ago

jupiterplanet commented 11 years ago

Hi Tobias,

I will try my best to describe this somehow strange behavior. I could not reproduce it in a plunk but locally it is reproducible. I have created a plunk so that you can copy and paste the contents into local files: http://plnkr.co/edit/RQKiqsjCWEDkubREKhLN

When I set a jqm transition to 'none' all jqm event handlers which I have tested are entered within the $digest-cycle meaning $rootScope.$$phase is equal to "$digest". For all other transition types I have tested $rootScope.$$phase is null.

As a consequence all changes made to the model within the event handler or any other function it calls are not properly propagated to the view and are only reflected within the next $apply/$digest cycle. This also occurs if I properly wrap the code into an $apply block.

It doesn't seem to matter how the transition is set. The described behavior occurs when a transition is set to none with $.mobile.defaultPageTransition, $location.routeOverride , $location.when or data-transition.

The event handlers I have tested include pagechange, pagebeforechange, pagebeforeshow, pageshow, pagebeforehide and pagehide.

To reproduce this behavior run these files locally, click on "Go to page" then click on "Go to index" and you will see that the alert box now says $digest. Change the code line data.options.transition = 'none'; at the end of app.js to data.options.transition = 'fade'; and you will see that the alert box always displays "null".

tbosch commented 11 years ago

Hi, ok, your problem is a result that you are using the jqm events directly (e.g. $(document).on('pageshow')) , and not the directives, that the adapter already provides (e.g. ngm-pageshow).

The adapter contains a patch which allows calling $apply from within $apply. So you can just always wrap your event handlers inside a $apply, as you would do without the adapter when you are reacting to a normal jquery event.

The reason why a plain event handler for a jqm event is called already within a $apply is due to the fact that jquery triggers some events form within other events. And that's also the reason why I added the patch for $apply to be called from within $apply...

Does this solve your problem? Tobias

jupiterplanet commented 11 years ago

Thanks for your reply and the background information. So it seems that my problem is not related to being in the $digest cycle. So no bug.

I have two pages. One showing a list of data records and the second one showing a list of details of each record. When I chose a record in the record list I display the details page. However, the details page is shortly displaying the old record details until the new ones are loaded. That's why I tried to set $scope.detailsList = null in the pagebeforeshow event handler (wrapped properly in an $apply block) as I hoped the ng-repeat directive would wipe out the details before the page is actually shown so that I see an empty details list until the new details are loaded. However, that doesn't seem to work. Using ngm-pagebeforeshow leads to the same result. It seems that the DOM modifications (in my case by the ng-repeat directive) due to the model change (in may case $scope.detailsList = null) are actually carried out when the page is already displayed in the browser.

It seemed to work with transitions set to e. g. 'fade'. But what I suspect is that as the transition takes time once the page transition has finished the ng-repeat has already cleared the list giving the illusion that it is working properly.

Cannot think of a solution at the moment but as this is not a bug I think we can close the issue. Maybe someone has a solution.

tbosch commented 11 years ago

Hi, using the adapter, each page as an own scope for performance reasons, e.g. a if one page contains a long list with a lot of bindings, this should not influence other pages. By this, pages are not rendered until they are shown. More exactly, until their pagebeforeshow event is triggered.

Closing this as not a bug... Tobias