opitzconsulting / jquery-mobile-angular-adapter

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

routing not working with Phonegap 2.6 #174

Closed xliyong closed 11 years ago

xliyong commented 11 years ago

I am trying the following simple setup using the adapter. The routing works on web browser, but fails on phonegap.

index.html

    <div data-role="content">
        <button ng-click="goto('/page1')">page1</button>
        <a href="/page2">page2</a>
    </div>

goto() function is defined in angularjs controller as $scope.goto = function(path){$location.url(path);}

app.js

    $routeProvider
        .when('/page1', {
        templateUrl: '/views/page1.html'
    })
        .when('/page2', {
        templateUrl: '/views/page2.html'
    })

I have logged the pagebeforeload event. From the log, the relative path has been resolved to be in file:/// path !?

Any ideas ?

04-18 18:06:38.069: D/CordovaLog(32660): pagebeforeload: 04-18 18:06:38.069: I/Web Console(32660): pagebeforeload: at file:///android_asset/www/scripts/application.js:51 04-18 18:06:38.069: D/CordovaLog(32660): url:/views/page1.html 04-18 18:06:38.069: I/Web Console(32660): url:/views/page1.html at file:///android_asset/www/scripts/application.js:52 04-18 18:06:38.069: D/CordovaLog(32660): absUrl:file:///views/page1.html 04-18 18:06:38.069: I/Web Console(32660): absUrl:file:///views/page1.html at file:///android_asset/www/scripts/application.js:53 04-18 18:06:38.069: D/CordovaLog(32660): dataUrl:/views/page1.html 04-18 18:06:38.069: I/Web Console(32660): dataUrl:/views/page1.html at file:///android_asset/www/scripts/application.js:54

xliyong commented 11 years ago

forgot to mention that I tested it on Android 4 device an iOS 6 simulator. Both are having the same issue.

And it seems that multi page template works well with angular routing.

It works If the route is defined as $routeProvider .when('/page1', { templateUrl: '#page1' }) But this would require me to write a huge combined template.

asgeo1 commented 11 years ago

I think that is expected behaviour.

Think about it - you are asking for a url "/views/page1.html". What does that mean? The leading slash means "start from the root of the domain".

When you are operating from your desktop browser, this means http://localhost:9000/views/page1.html or http://mydomain/views/page1.html

But when you are operating in Cordova, there is no domain because you are working on the file:/// protocol. So the url "/views/page1.html" maps to file:///views/page1.html

Obviously there is no such file /views/page1.html on your android operating system. So it fails.

I had some luck in integrating jquery-mobile-angular-adapter with Cordova. But I had to call the templates with relative urls, not absolute:

$routeProvider
  .when('/page1', {
    templateUrl: 'views/page1.html'
  })

There are still other issues getting anchors (<a href="") working such that they will from both http:// and file:/// - some of that can be solved by setting the base url in the jquery mobile page:

<div data-role="page" data-url="{{location.baseUrl}}">
</div>

angular.module('myApp')
  .controller 'AppCtrl', ['$rootScope', ($rootScope) ->
    $rootScope.location = {
      baseUrl: $('base').attr 'href'
    }

Still not sure if that's a good way of dealing with it or not, but it's working for me for now.

xliyong commented 11 years ago

Thanks . That solved my problem.

Thought I have got another problem with form handling.

ng-submit should prevent jquery mobiles form submit handling, and action attribute is not needed in the form.

So the following code snippet should work.

<form ng-submit="addTodo()" data-ajax="false">
<input type="text" id="inputText" ng-model="data.inputText" placeholder="enter your todo here" ng-model-instant>
</form>

But in my setup, it only works if the form is in index page.

If the form in views/page1.html does not have action attribute, jquery mobile won't load it.

92 seems to be related. But the fix for #92 is to activate $.support.dynamicBaseTag, which is false by default.

Have you encountered it before ?

asgeo1 commented 11 years ago

Yeah, I've had issues with preventing forms from submitting.

I had to ensure that I specified a "src" attribute. I've forgotten why - obviously forms don't have src attributes. However, when I was debugging, I found that jQuery Mobile was expecting a src attribute.

  <form name="lookupItem" ng-submit="lookupItem(itemNumber)" data-ajax="false" src="">
  </form>
xliyong commented 11 years ago

It is related to $.support.dynamicBaseTag support.

Looking at jQuery Mobile source, it is expecting to find action attributes and rewrite them. Adding src="" attribute to form tag would make the code go through without handling form submission; otherwise, thisUrl would be undefined if action attribute is not defined.

//rewrite src and href attrs to use a base url
if ( !$.support.dynamicBaseTag ) {
    var newPath = path.get( fileUrl );
    page.find( "[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]" ).each(function() {
        var thisAttr = $( this ).is( '[href]' ) ? 'href' :
                $( this ).is( '[src]' ) ? 'src' : 'action',
            thisUrl = $( this ).attr( thisAttr );

        // XXX_jblas: We need to fix this so that it removes the document
        //            base URL, and then prepends with the new page URL.
        //if full path exists and is same, chop it - helps IE out
        thisUrl = thisUrl.replace( location.protocol + '//' + location.host + location.pathname, '' );

        if ( !/^(\w+:|#|\/)/.test( thisUrl ) ) {
            $( this ).attr( thisAttr, newPath + thisUrl );
        }
    });
}
xliyong commented 11 years ago

Looks like routing the index page is not working with Phonegap (2.6).

When running on desktop / mobile browsers, the original index.html page might show up and then browser would switch to the view defined in routeProvider immediately.

With phonegap, $routeChangeStart event isn't fired at all, and index.html shows up.

Any ideas ? Thanks in advance.

$routeProvider
  .when('/', {
    templateUrl: 'views/page.html'
  })
tbosch commented 11 years ago

Hi, ok, there are multiple issues involved here, trying to sort them out:

  1. The initial problem was due to the fact that templateUrl was an absolute not a relative path, as stated correctly by @asgeo1.
  2. An issue by @asgeo1 "There are still other issues getting anchors (<a href="") working such that they will from both http:// and file:///...": Could you create an own issue for this? This should work and we have an example app that is working in both, phonegap and webserver...
  3. A problem with form submitting by @leyonh. Will comment on that later.
  4. A problem for specifying an external template as initial page. If you open your app via http server using the url http://someServer/somePath/ and your index.html is in /somePath/index.html, you need the routing .when('/'...). If you open the app with a link to the index.html, i.e. http://someServer/somePath/index.html you need a route for .when('/index.html'...). Phonegap always opens your app using the later case. So for phonegap your initial route should be .when('/index.html'...).

Tobias

tbosch commented 11 years ago

The Problem with form submitting is a known jqm bug: https://github.com/jquery/jquery-mobile/issues/4896 And the workaround is, as @asgeo1 suggested, to add a src="" attribute to the form.

With this, all problems seems to be solved, except for 2. by @asgeo1. As I mentioned, please open another issue for this if needed...

And thanks, @asgeo1 for providing the answers for 1. and 3.!

Tobias

roy650 commented 9 years ago

Hi @tbosch, I seem to be running into the issue described by @asgeo1 as number 2. on your list above - However, I can't seem to understand the implementation suggested by @asgeo. Has there been any follow up issue for this or a resolution for this problem? Thanks, Roy