After brainstorming, I devised a solution: ( click 'Locations' and the table row on this demo )
I included the id and name parameters within $stateProvider.state
url: "location/:lid/:name",
If 'lid' was left unspecified, 'name' would also be missing, resulting in 'location//' displayed in the URL. In such cases, setting lid = 'all' and name = '' informs the controller to display all locations instead of a specific one.
lid: function($stateParams){
$stateParams.lid = $stateParams.lid || 'all';
return $stateParams.lid;
},
Next, I made lid a dependency and injected it into getName. Utilizing $q as an alternative to $http demonstrated that promises work effectively here for the subsequent dependency with a random timeout duration.
getName: ['$q','$timeout','lid', function($q, $timeout, lid){
var deferred = $q.defer();
$timeout(function() {
var names = ['Cool Place', 'Awesome place', 'boring place', 'I want to be here', 'Random Venue'];
deferred.resolve(names[ parseInt(lid) % 4 ]);
}, Math.round(Math.random()*200));
return deferred.promise;
}],
Then, I injected getName and lid into name:
name : ['lid', '$state','$stateParams','getName', function (lid, $state, $stateParams,getName) {
if($stateParams.lid.length < 1 || $stateParams.lid == 'all'){
$stateParams.name = '';
return '';
}
if($stateParams.name.length > 0){
return $stateParams.name;
}
getName = getName.replace(/\s/g,'-');
$state.transitionTo('dashboard.location', {lid:lid, name:getName}, {
reload:true,
inherit:false,
notify:true
})
}]
If the name is absent from the parameters, transitioning with a 'reload' property set to true is necessary.
A comprehensive demo can be accessed by ( clicking 'Locations' and the table row on this demo )
To summarize everything:
.state('dashboard.location', {
templateUrl : "apps/location/template/location_template.htm",
controller: 'LocationCtrl',
url: "location/:lid/:name",
resolve: {
ctrl: function($ocLazyLoad){
return $ocLazyLoad.load({
name: "dashboard.location",
files: ['apps/location/location_controller.js', 'apps/location/style/location.css']
});
},
lid: function($stateParams){
$stateParams.lid = $stateParams.lid || 'all';
return $stateParams.lid;
},
getName: ['$q','$timeout','lid', function($q, $timeout, lid){
var deferred = $q.defer();
$timeout(function() {
var names = ['Cool Place', 'Awesome place', 'boring place', 'I want to be here', 'Random Venue'];
deferred.resolve(names[ parseInt(lid) % 4 ]);
}, Math.round(Math.random()*200));
return deferred.promise;
}],
name : ['lid', '$state','$stateParams','getName', function (lid, $state, $stateParams,getName) {
if($stateParams.lid.length < 1 || $stateParams.lid == 'all'){ // show all or not set Location ID
$stateParams.name = '';
return '';
}
if($stateParams.name.length > 0){ // if the name is already specified, it's ok. settle
return $stateParams.name;
}
getName = getName.replace(/\s/g,'-');
$state.transitionTo('dashboard.location', {lid:lid, name:getName}, {
reload:true,
inherit:false,
notify:true
})
}]
}
})
This detailed guide may assist others in similar scenarios.