Angular UI Router - Dynamic states get double slashes when navigating with ui-sref

I am building a CMS system so I want the states to be dynamically generated. Since you cannot create HTTP requests in the configuration phase, I decided to add my routes to the .run () function as described here: http://blog.brunoscopelliti.com/how-to-defer-route-definition-in- an-angularjs-web-app

Now when I display a list of links in my partial navigation using the ui-sref directive, the url being added has two forward slashes instead of one. The controller and everything is named accordingly, but I can't seem to get rid of the double slashes. Any ideas?

Here's the relevant code:

app.js

var $stateProviderReference;

angular.module('app', [
    'ui.router',                // Angular UI Routing
    'ngStorage',                // Angular Storage (local, cookies, session)
    'ngAnimate',                // Angular Animation
    'angular-loading-bar',      // Angular Loading Bar
    'restangular',              // Restangular
    'angular.assets.injector',  // Custom assets injector
])
.config(function($stateProvider, $urlRouterProvider, RestangularProvider, $httpProvider, cfpLoadingBarProvider){

    // Save a reference of our stateProvider
    $stateProviderReference = $stateProvider;

    // Irrelevant configuration

    // States (routes)
    $stateProvider

        /*
         |
         | Frontend
         |
         */
        .state('frontend', {
            url: '/',
            views: {
                '': { 
                    templateUrl: 'app/views/frontend/templates/default/bootstrap.html',
                    controller: 'FrontendCtrl'
                },
                'nav@frontend': {
                    templateUrl: 'app/views/frontend/templates/default/partials/navigation.html',
                    controller: 'NavCtrl',
                    resolve: {
                        pages: function(PageService){
                            return PageService.all();
                        }
                    }
                },
                'footer@frontend': {
                    templateUrl: 'app/views/frontend/templates/default/partials/footer.html',
                    controller: 'FooterCtrl'
                },
                'page@frontend': {
                    templateUrl: 'app/views/frontend/pages/page.html',
                    controller: 'PageCtrl'
                }
            }
        });

.run(function($rootScope, $location, $state, $stateParams, AuthService, CSRF_TOKEN, PageService){

    // Retrieve all the pages
    PageService.all().then(function(pages){

    // Loop through all the pages
    angular.forEach(pages, function(page){

        // If this is not the homepage
        if( page.routeName !== 'frontend' )
        {
            // Add a state to our stateProvider
            $stateProviderReference.state(page.routeName, {
                // Set the desired url
                url: page.url,
                // Views that we are populating
                views: {
                    // Override the page view partial
                    'page@frontend': {
                        templateUrl: 'app/views/frontend/pages/page.html',
                        controller: 'PageCtrl'
                    }
                }
            });
        }

    });

});

      

navigation.html partial

<ul class="nav navbar-nav">
    <li ng-repeat="page in pages">
        <a ng-class="{'active': isActive({{page.routeName}})}" ui-sref="{{ page.routeName }}">{{ page.title }}</a>
    </li>
</ul>

      

The page data retrieved from the db is formatted like this:

{
    id: 1,
    routeName 'frontend.home',
    title: 'Homepage',
    url: '/home',
    metaData: {
        tags: "some random tags",
        desc: "some random description"
    },
    content: "Html goes here",
    deletable: 'yes' // or 'no'
}

      

So everything works, except for the double slashes. When I click on the link generated for the above sample code, it will send me the following URL:

http://localhost/CMSv2/public/#//home

      

instead

http://localhost/CMSv2/public/#/home

      

I tried removing the slash from the routeName property and then adding no double slashes, but the controller can no longer be reached and everything seems to break.

+3


source to share


2 answers


The problem comes from the fact that if there are parent elements parent, then their url is parent.url + child.url:

  • parent: .state('frontend', { url: '/',...

  • child: { routeName 'frontend.home', url: '/home',..

  • result: '/' + '/home' === '//home'

But again there is a good solution built in ui-router

:

small cite:

If you want to have an absolute URL match, you need to attach the url string with the special character "^".



$stateProvider
  .state('contacts', {
     url: '/contacts',
     ...
  })
  .state('contacts.list', {
     url: '^/list',
     ...
  });

      

SOLUTION: (very simple in this case)

Instead url def:

{
    id: 1,
    routeName 'frontend.home',
    title: 'Homepage',
    url: '/home',
    ...

      

We'll just send this one : url: '^/home',

{
    id: 1,
    routeName 'frontend.home',
    title: 'Homepage',
    url: '^/home',
    ...

      

+5


source


Since your home state comes from frontend state, an extra forward slash is added from the frontend. To remove the extra leading slash, set the frontend-state to "abstract" and clear the url like this:

.state('frontend', {
    abstract: true,
    url: '',
    templateUrl: 'yourTemplate.html'
})

      



This fits your structure better since the frontend url is never used.

+4


source







All Articles