13

I'm using ui-router for state management but I think I'm having trouble with my .htaccess rewrite rules. All my states worked when using /#/account style urls. Now I've enabled html5 mode but my app isn't rendering as it was before. It seems to load my index.html and all my js and css files, etc. but not actually initialise any states.

Here is my folder structure:

root/
    app/
        components/
            angular/
            ...
        images/
        scripts/ 
            controllers/
            directives/
            ...
            app.js       
        styles/
        views/
        .htaccess
        ...

My vhosts DocumentRoot points to my app/

Here is my app.js with my states:

'use strict';

angular.module('appointeddPortalApp',  ['ngResource', 'ui.state', 'ui.compat', 'fundoo.services', 'ui.date', 'ngCookies'])
.config(function ($stateProvider, $routeProvider, $locationProvider, $httpProvider) {

    var access = routingConfig.accessLevels;

    delete $httpProvider.defaults.headers.common["X-Requested-With"];
    $httpProvider.defaults.useXDomain = true;
    $locationProvider.html5Mode(true);

    $stateProvider
    .state('root', {
        abstract: true,
        url: '',
        views: {
            'header': {
                templateUrl: 'views/partials/header.html'
            },
            'search': {
                templateUrl: 'views/partials/search.html',
                controller: 'SearchCtrl'
            },
            'main': {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'
            },
            'footer': {
                templateUrl: 'views/partials/footer.html'
            },
        },
    })
    .state('root.home', {
        url: '',
        views: {
            'content': {
                templateUrl: 'views/home/index.html',
                controller: 'MainCtrl',
            }
        },
        access: access.anon
    })
    .state('root.about', {
        url: '/about',
        parent: 'root',
        views: {
            'content': {
                templateUrl: 'views/about.html',
                controller: 'StaticCtrl'
            },
            'search@': {}
        },
        access: access.anon
    })
    .state('root.search', {
        url: '/search/:city/:category',
        views: {
            'content': {
                templateUrl: 'views/search.html',
                controller: 'SearchCtrl'
            }
        },
        access: access.anon
    })
    .state('root.salons_profile', {
        url: '/salons/{id}',
        views: {
            'content': {
                templateUrl: 'views/salons.profile.html',
                controller: 'SalonCtrl',
            },
            'search@': {}
        },
        access: access.anon
    })
    .state('root.account', {
        url: '/account',
        abstract: true,
        views: {
            'content': {
                templateUrl: 'views/user/account.html',
                controller: 'AccountCtrl'
            }
        },
    })
    .state('root.account.info', {
        url: '',
        views: {
            'account_head': {
                templateUrl: 'views/user/account.head.html',
            },
            'account_body': {
                templateUrl: 'views/user/account.my_appointedd.html',
            },
        },
        menus: {
            'account': {
                identifier: 'my_appointedd',
                class: 'active'
            }
        },
        access: access.user
    })
    .state('root.account.appointments', {
        url: '/appointments',
        views: {
            'account_head': {
                templateUrl: 'views/user/account.head.html',
            },
            'account_body': {
                templateUrl: 'views/user/account.appointments.html',
            },
        },
        menus: {
            'account': {
                identifier: 'appointments',
                class: 'active'
            }
        },
        access: access.user
    })
    .state('root.account.details', {
        abstract: true,
        views: {
            'account_head': {
                templateUrl: 'views/user/account.head.html',
            },
            'account_body': {
                templateUrl: 'views/user/account.details.html',
            },
        },
        access: access.user
    })
    .state('root.account.details.account', {
        url: '/details',
        views: {
            'right': {
                templateUrl: 'views/user/account.details.account.html',
            },
        },
        menus: {
            'account': {
                identifier: 'details',
                class: 'active'
            },
            'settings': {
                identifier: 'account',
                class: 'active'
            }
        },
        access: access.user
    })
    .state('root.account.details.profile', {
        url: '/profile',
        views: {
            'right': {
                templateUrl: 'views/user/account.details.profile.html',
            },
        },
        menus: {
            'account': {
                identifier: 'details',
                class: 'active'
            },
            'settings': {
                identifier: 'profile',
                class: 'active'
            }
        },
        access: access.user
    });


})
.run( [ '$location', '$state', '$stateParams', '$rootScope', '$cookies', 'Auth', function( $location, $state, $stateParams, $rootScope, $cookies, Auth){

    $rootScope.client_id = '51a741eb3152c3ae7e000103';
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
    $rootScope.$cookies = $cookies;

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        if (!Auth.authorize(toState.access)) {
            if(Auth.isLoggedIn()) $state.transitionTo('root.account');
            else                  $state.transitionTo('root.home');
        }
    });

Here is my rewrite code that sits in .htaccess in /app. I think this is might be wrong.

<IfModule mod_rewrite.c>
  Options +FollowSymLinks 
  RewriteEngine On 
  RewriteBase / 
  RewriteRule ^(components|images|scripts|styles|views)($|/) - [L]
  RewriteRule ^(.*)$ index.html [L]
</IfModule>

2 Answers 2

40
+100

This configuration has worked for many of our Apache users using html5mode and ui-router.

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

        # Don't rewrite files or directories
        RewriteCond %{REQUEST_FILENAME} -f [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^ - [L]

        # Rewrite everything else to index.html to allow html5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

Also please make sure you are not a victim of <base href> bug. See the ui-router FAQ for more info.

Sign up to request clarification or add additional context in comments.

7 Comments

Hi nfiniteloop, it seems my issue was the <base href> bug! Thanks!
you rock. +1. noobs... you can drop everything from inside the <Directory node into .htaccess on root and you'll have the same effect on your web host. cheers!
in drupal how will is set when i set this rule 500 Internal Server Error comes please help
But is then not every route lost and I get always redirected to home? E.g. mypage.de/abc will be redirected to mypage.de/index.html instead of mypage.de/#/abc
This doesn't seem to work with child states "admin.classes". I get a 404 not found. I did add this rule to my htaccess file: RewriteRule ^admin/(.*)$ /$1 [R,L]. When i do a page reload on /admin/classes. I get routed to /classes.
|
3

If working in a shared hosting that doesn't allow to edit Apache configuration you can set this in your .htaccess file to make $locationProvider.html5Mode(true) work (as @Shanimal pointed in @nfiniteloop answer):

RewriteEngine on

RewriteBase /path/to/app #change this!

# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]

# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]

And don't forget to add <base href="/path/to/app/"> in the HTML <head>.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.