Because I have to build my urls SEO friendly and because I can't trust the user output. I want redefine this input when the resolve function returns me success.
Example :
The user writes : http//mydomain.com/city/Newcastle upon Tyne .
The API returns me the correct slug : newcastle-upon-tyne-0191 and loads the template.
I want reverse the user inputs with this slug like this before the templates load :
http//mydomain.com/city/newcastle-upon-tyne-0191.
I'm using UI router, it is a way for do this ($state, $stateparams) ?
Here is the part of my router code which work with :
.state('villes.ville', {
url: "/:ville",
cache: false,
parent: 'villes',
templateUrl: "partials/ville.tpl.html",
metaTags: {
title: '{{city.label}} ({{city.zip_code}})',
},
resolve: {
city: function(City, $state, $stateParams){
return City.get({
slug: $stateParams.ville,
shape: true,
details: true
}).$promise.then(
function(data){ return data },
function(error){ $state.go('/404') });
}
},
controller : 'villeCtrl'
})
Related
I am implementing meta tags in angularjs using this code :
.state('home', {
url: "/home/",
metaTags: {
title: 'abc',
description: 'xyz',
keywords: 'xyz',
properties: {
'og:title': abc'
}
},
views : {
"" : {
templateUrl:"/home/home.html",
controller: 'homeCtrl',
controllerAs:'vm',
}
},
resolve: {
loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
return $ocLazyLoad.load('home'); // Resolve promise and load before view
}]
}
})
It is working fine because I fixed the meta tags but, I want to send dynamic data from a controller to mainApp.
In easy way , I want to send dynamic data from homeCtrl to mainApp.
Is there any way to do this in angularjs?
Thanks in advance.
https://docs.angularjs.org/api/ng/service/$rootScope (rootScope usage guide and doc)
https://www.w3schools.com/angular/angular_scopes.asp (Usage examples)
I want to navigate from one url /projects to url /projects/{name} , but I need to resolve resource by $stateParams.id. How can I do it?
Now I have something like this:
$stateProvider.state('project.detail', {
...
url: '/projekt/{name}/{id}',
...
resolve: {
project: ['$stateParams', 'ProjectService', function($stateParams, ProjectService) {
return ProjectService.get({id : $stateParams.id}).$promise;
}]
}
...;
But when I remove {id} from the url: '...', it does not work.
My front end navigation is :
ui-sref="project.detail({name: project.name, id: project.id})"
And I do not want to have url .../projects/hyperloop/5462
but only .../projects/hyperloop
Thank you!
You can use parameters without specifying them in state URLs. You can specify them in params property in state config:
$stateProvider.state('project.detail', {
...
url: '/projekt/{name}',
params: {
id: null
},
resolve: {
project: ['$stateParams', 'ProjectService', function($stateParams, ProjectService) {
return ProjectService.get({id : $stateParams.id}).$promise;
}]
}
...
})
Please check ui-router docs for more details
I have this code in my angular app. So as the code says, there are multiple views being loaded and I want to pass one parameter.
.state('root.moduleListing', {
params: ['registerData'],
views: {
"main_container": {
controller: 'ModuleListingController as model',
templateUrl: 'misc/module-listing/module-listing.tpl.html',
resolve: {
registerData: ['$stateParams', function($stateParams) {
return $stateParams.registerData;
}]
}
},
"components_header_header": {
controller: 'HeaderController as model',
templateUrl: 'components/header/post-login.tpl.html',
},
"components_footer_footer": {
controller: 'FooterController as model',
templateUrl: 'components/footer/footer.tpl.html',
}
}
}
& I am calling it using
$state.go('root.moduleListing', {'registerdata': response});
& in controller, I am just trying to log it to the console.
module.controller('ModuleListingController', function ($scope, $state, registerData) {
var model = this;
console.log("registerData : " + registerData);
}
Now the app doesn't even start i.e. I get an error in the console saying:
failed to instantiate module amcatUI due to:
TypeError: id.match is not a function
at getArrayMode
Type of defined parameters and toParamas of $state.go should be same array or object on both sides of state transition. Just add your parameters with a default value on your state definition.
You need to update your code from
params: ['registerData'],
to
params: {'registerData' : null},
You can refer to "https://stackoverflow.com/a/26204095/1132354" for detailed answer.
Edit
Also, you will need to update
$state.go('root.moduleListing', {'registerdata': response});
to
$state.go('root.moduleListing', {'registerData': response});
There is a small typo error.
I an trying to list out all the URL's that exist in the stateprovider (angularjs 1.2.26).
given the example below, (very much cut down state list):
angular.module('app')
.config(function ($stateProvider) {
$stateProvider
.state('app.vendors', {
url: '/vendors',
templateUrl: 'app/vendor/list.html',
controller: 'Vendor.ListController as vm',
})
.state('app.vendor', {
url: '/vendor/{vendorId}',
templateUrl: 'app/vendor/details.html',
controller: 'Vendor.DetailsController as vm',
data: {
subnav: [
{ title: 'Details', icon: 'fa-align-left', state: 'app.vendor', permissions: 'get-vendor', exactStateOnly: true },
{ title: 'Sites', icon: 'fa-archive', state: 'app.vendor.sites', permissions: 'get-site' },
{ title: 'NCRs', icon: 'fa-copy', state: 'app.vendor.ncrs', permissions: 'get-vendor' }
],
requiredPermissions: ['get-vendor']
}
})
.state('app.vendor.sites', {
url: '/sites',
templateUrl: 'app/vendor/site/list.html',
controller: 'Vendor.Site.ListController as vm',
data: {
requiredPermissions: ['get-site']
}
})
.state('app.vendor.site', {
url: '/site/{siteId}',
templateUrl: 'app/vendor/site/details.html',
controller: 'Vendor.Site.DetailsController as vm',
data: {
requiredPermissions: ['get-site']
}
})
.state('app.vendor.ncrs', {
url: '/ncrs',
templateUrl: 'app/vendor/ncr/ncrList.html',
controller: 'Vendor.NCR.NCRListController as vm',
data: {
requiredPermissions: ['get-vendor']
}
});
});
to get to a particular vendor you would use state:
app.vendor({vendorId: 1})
to get to its site
app.vendor.site({vendorId: 1, siteId: 2})
if I pass in the $state object to a controller I can list all the states with state.get().
If I list them the urls only contain the last part (i.e. what is in the config, and relative to its parent). I can use $state.href('app.vendor.site') which will give me almost the whole url, but misses out the parameters. I am trying to find a way at runtime to know what or at least how many parameters it requires.
My goal is to try and create a basic smoke test for every page in our Angular app to ensure it loads something and doesn't through errors in the console. I dont want to have to manually maintain a list of urls with params. (all our params are int IDs so I can simply use "1" in the params to test the url).
The private portion of the state contains params and ownParams objects. You can use a decorator to access those internal variables. See my previous answer regarding exposing the entire internal state object using a decorator: UI-Router $state.$current wrapper for arbitary state
After decorating your state objects, use the $$state() function to retrieve the private portion. Then query the state for its params and generate the href.
angular.forEach($state.get(), function(state) {
var paramKeys = state.$$state().params.$$keys();
var fakeStateParams = {};
angular.forEach(paramKeys, function(key) { fakeStateParams[key] = key; });
console.log($state.href(state, fakeStateParams));
});
So consider the following fragment from my angularUI routing setup. I am navigating to the route /category/manage/4/details (for example). I expect 'category' to be resolved before the relevant controller loads, and indeed it is to the extent that I can put a breakpoint inside the resolve function that returns the category from the category service and see that the category has been returned. Now putting another breakpoint inside the controller itself I can see that 'category' is always undefined. It is not injected by UI router.
Can anyone see the problem? It may be somewhere other than in the code I've provided but as I have no errors when I run the code, it's impossible to tell where the source of the issue might lie. Typical js silent failures!
.state('category.manage', {
url: '/manage',
templateUrl: '/main/category/tree',
controller: 'CategoryCtrl'
})
.state('category.manage.view', {
abstract: true,
url: '/{categoryId:[0-9]*}',
resolve: {
category: ['CategoryService', '$stateParams', function (CategoryService, $stateParams) {
return CategoryService.getCategory($stateParams.categoryId).then(returnData); //this line runs before the controller is instantiated
}]
},
views: {
'category-content': {
templateUrl: '/main/category/ribbon',
controller: ['$scope', 'category', function ($scope, category) {
$scope.category = category; //category is always undefined, i.e., UI router is not injecting it
}]
}
},
})
.state('category.manage.view.details', {
url: '/details',
data: { mode: 'view' },
templateUrl: '/main/category/details',
controller: 'CategoryDetailsCtrl as details'
})
The concept is working. I created working plunker here. The changes is here
instead of this
resolve: {
category: ['CategoryService', '$stateParams', function (CategoryService, $stateParams) {
//this line runs before the controller is instantiated
return CategoryService.getCategory($stateParams.categoryId).then(returnData);
}]
},
I just returned the result of the getCategory...
resolve: {
category: ['CategoryService', '$stateParams', function (CategoryService, $stateParams) {
return CategoryService.getCategory($stateParams.categoryId); // not then
}]
},
with naive service implementation:
.factory('CategoryService', function() {return {
getCategory : function(id){
return { category : 'SuperClass', categoryId: id };
}
}});
even if that would be a promise... resolve will wait until it is processed...
.factory('CategoryService', function($timeout) {return {
getCategory : function(id){
return $timeout(function() {
return { category : 'SuperClass', categoryId: id };
}, 500);
}
}});