javascriptangularjsangular-ui-routernested-views

A parameter of ui-router in controller and resolve


I have configured the following ui-router.

app.config(['$stateProvider', function ($stateProvider) {
    $stateProvider
        .state('global.editor', {
            url: '/posts/editor/{id}',
            templateUrl: '/htmls/editor.html',
            controller: 'EditorCtrl',
            resolve: {
                post: ['$stateParams', 'codeService', function ($stateParams, codeService) {
                    return codeService.getPost($stateParams.id)
                }]
            }
        }
        .state('global.new', {
            url: '/new',
            templateUrl: '/htmls/editor.html',
            controller: 'EditorCtrl'
        })
        .state('global.newTRUE', {
            url: '/newTRUE',
            templateUrl: '/htmls/editor.html',
            controller: 'EditorCtrl'
        })           
        .state('global.editor.panels', {
            controller: 'PanelsCtrl',
            params: { layout: 'horizontal' },
            templateUrl: function (params) { return "/htmls/" + params.layout + '.html' }
        }
}])

app.controller('EditorCtrl', ['$scope', '$state', function ($scope, $state) {
    $scope.layout = "horizontal";
    $scope.$watch('layout', function () {
        $state.go('global.editor.panels', { layout: $scope.layout });
    });
}]);

As a result, https://localhost:3000/#/new in a browser leads to (the state global.editor, then to) the state global.editor.panels.

Now, I want to add a parameter connected:

  1. I don't want it to be shown in the url
  2. https://localhost:3000/#/new in a browser makes connected to be false, and https://localhost:3000/#/newTRUE in a browser makes connected to be true
  3. connected can be past into the controller EditorCtrl and PanelsCtrl
  4. connected can be available in the resolve of global.editor; ideally, we could resolve different objects according to the value of connected.

Does anyone know how to accomplish this?


Solution

  • You can surely use the params of UI-Router states' config to not show it in URL and achieve all mentioned points.

    Also, as per #2, you need connected to be false for /new and true for /newTRUE. We can do so by passing true or false as default value for those states. Something like this:

    $stateProvider
        .state('global.editor', {
            url: '/posts/editor/{id}',
            templateUrl: '/htmls/editor.html',
            params: { connected: null },
            controller: 'EditorCtrl',
            resolve: {
                post: ['$stateParams', 'codeService', function ($stateParams, codeService) {
                    return codeService.getPost($stateParams.id)
                }]
            }
        }
        .state('global.new', {
            url: '/new',
            templateUrl: '/htmls/editor.html',
            params: { connected: false }, // default false for /new
            controller: 'EditorCtrl'
        })
        .state('global.newTRUE', {
            url: '/newTRUE',
            templateUrl: '/htmls/editor.html',
            params: { connected: true }, // default true for /newTRUE
            controller: 'EditorCtrl'
        })           
        .state('global.editor.panels', {
            controller: 'PanelsCtrl',
            params: { layout: 'horizontal', connected: null },
            templateUrl: function (params) { return "/htmls/" + params.layout + '.html' }
        }
    

    For #3, In order to access connected in your controllers (EditorCtrl and PanelsCtrl) you can inject $stateParams to controller and use $stateParams.connected to get it.

    For #4, (This is more or less similar to achieveing #3)

    Just like you get $stateParams.id, you can have $stateParams.connected as well, which you can use to resolve different objects according to the value of connected. Something like this:

    .state('global.editor', {
        url: '/posts/editor/{id}',
        templateUrl: '/htmls/editor.html',
        params: { connected: null },
        controller: 'EditorCtrl',
        resolve: {
            post: ['$stateParams', 'codeService', function ($stateParams, codeService) {
                return $stateParams.connected ? 
                    codeService.getPost($stateParams.id) :
                    codeService.getSomethingElse($stateParams.id) 
            }]
        }
    }
    

    But, for that to work, make sure that you are passing connected as params when you visit global.editor state (using $state.go or ui-sref)

    Hope this helps!