Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS and Laravel 4 routing conflict in HTML5 mode

I would like to remove the # hash from URLs using Angularjs' $locationProvider.html5Mode(true).

Example: The address bar displays http://localhost/shop instead of http://localhost/#/shop.

Everything works well untill I refresh a page. If i refresh, the following Laravel Route (defined in routes.php) is accesed

Route::resource('shop', 'ShoppingController')

not the AngularJS Route (defined in app.js)

$routeProvider.when('/shop', { 
    templateUrl: 'templates/shop.html', 
    controller: 'ShoppingController' 
});

My Code:

routes.php (Laravel Routes)

Route::get('/', function() {
    return View::make('index'); 
});
Route::resource('shop', 'ShoppingController'); 

app.js (AngularJS Routes)

var app = angular.module('shoppingApp',['ngRoute','SharedServices']); 

app.config(function($routeProvider, $locationProvider) { 
    $routeProvider.when('/shop', {
        templateUrl: 'templates/shop.html', 
        controller: 'ShoppingController'
    });
    $routeProvider.otherwise({ redirectTo: '/' }); 
    $locationProvider.html5Mode(true); 
});

My directory structure:

Project
    /app 
        /...
        /views
            -index.php (single page application file)
            -routes.php (Laravel routes)
    /public
        /...
        /js
            -angular.js
            -app.js
        -index.php (Laravel index file)

Tried Solutions:

Rewrite the htaccess file so that all requests are redirected to index.php (the single page application file, from where AngularJS would take over the routing). Problem: In this way the Laravel route (Route::resource('shop', 'ShoppingController'); - necessary for interaction with the database) becomes inaccessible to the AngularJS $http service:

app.js

app.controller("ShoppingController", function($scope, $http) {
    $http.get('/shop', { cache: true}).
        success(function(data, status) {
        $scope.items = data
    }).
    error(function(data, status) {
        console.log('Status: ' + status);
        });
});

Question: How can I solve the routing problem, so that the AngularJS route, not the Laravel Route gets accessed if I refresh localhost/shop?

like image 932
user1894374 Avatar asked Jan 25 '14 22:01

user1894374


2 Answers

From what I read, it seems like Laravel is reading the modified route when you refresh the page. In this case, you should make Laravel continue to make the original view even if it would otherwise be a 404 redirect.

Try adding the following somewhere on the Laravel side (Ex. routes.php)

App::missing(function($exception)
{
    return View::make('index');
});

Note: You might want to have AngularJS's routing use .otherwise to handle pages that are not found.

like image 97
Snowdrop Avatar answered Nov 16 '22 00:11

Snowdrop


A better solution is to redirect this way:

'Redirect::to('/#/' . Request::path())'

When you refresh or go to the URI directly:

  • 'Request::path()': returns the requested URI i.e. ('/shop/categories/electronics');
  • AngularJS in 'html5Mode' still responds to the '#/' prefix;
  • If angular detects the prefix when in HTML5 mode it will remove the prefix for you.

Final solution:

App::missing(function($exception) {
    return Redirect::to('/#/' . Request::path());
});
like image 44
Wesley Stam Avatar answered Nov 15 '22 23:11

Wesley Stam