I've upgraded my version of Angular to 1.7.8 and also upgraded angular-ui-router to 1.0.22.
After upgrade my resolved data from the router configuration isn't working (anymore).
Route configuration:
$stateProvider.state('app', {
views: {
'#' : {
templateUrl: CONFIG.BasePath + '/article/views/layout.html'
},
'article#app': {
templateUrl: CONFIG.BasePath + '/article/views/index.html',
controller: 'ArticleController',
resolve : {
settings: function() {
return {
someValue: ''
};
},
deps: ['$ocLazyLoad', function($ocLazyLoad) {
// other code
}]
}
}
}})
Controller:
function MapController ($scope, settings) {
console.log(settings);
}
MapController.$inject = [
'$scope',
'settings'
];
When I try to access it from the resolves object, it works, but this is not the way to go imho...
function MapController ($scope) {
console.log($scope.myResolves.$state$.views['article#app'].resolve.settings());
}
MapController.$inject = [
'$scope'
]
ui-router 1.0 does not support resolve into views:
We no longer process resolve blocks that are declared inside a views.
you need to rewrite it and move resolves out to a resolve block on the state:
Now, move all resolves out to a resolve block on the state:
Read here for more details and examples: ui-router
Related
The docs and stuff I've seen show how to use the "resolve" option but how do you get the data back?
I'm using meanjs.org v0.3.x
My route:
//Setting up route
angular.module('mymodule').config(['$stateProvider',
function($stateProvider) {
//start routing
$stateProvider.
state('some-path', {
url: '/some-url',
templateUrl: 'modules/mymodule/views/my-controller.client.view.html',
resolve: {
DataService: 'DataService',
promiseToResolve: function(DataService){
return DataService.get({});
}
}
});
}
]);
Now how exactly to I access the "promiseToResolve" data in my controller? Docs don't seem to mention this.
Also, please let me know if the above code would break when it is minified.
angular.module('mymodule').config(['$stateProvider',
function($stateProvider) {
//start routing
$stateProvider.
state('some-path', {
url: '/some-url',
templateUrl: 'modules/mymodule/views/my-controller.client.view.html',
controller: mySpecialController,
resolve: {
promiseToResolve: ['DataService', function(DataService) {
return DataService.get({});
}]
}
});
}
]);
You don't need the specific DataService line, so it's removed, and now in your controller (which you've specified in the above code) you can directly access the resolved data:
angular.module('mymodule').controller('mySpecialController', ['$scope', 'promiseToResolve',
function ($scope, promiseToResolve) {
$scope.dataResults = promiseToResolve.data;
}
]);
As for minification, here we use ngInject which is great.
I have various states that use the same resolve to load a timeLog into my controller $scope before the controller loads. I would like to not reproduce this code but share it between these views. I'm fairly new to JS frameworks, and especially Angular JS.
I'm having a hard time googling this and not finding any decent information. Maybe I'm searching incorrectly or not thinking about this correctly. Any Suggestions?
.config(function($stateProvider) {
$stateProvider
.state('tab.edit-log-summary', {
url: '/logs/edit-log-summary/:timeLogId',
views: {
'tab-logs': {
templateUrl: 'templates/logs/edit-log-summary.html',
controller: 'EditLogSummaryCtrl'
}
},
resolve: {
timeLog: function(config, $stateParams, DailyLog) {
return DailyLog.get({id: $stateParams.timeLogId});
},
}
})
.state('tab.edit-time-log', {
url: '/logs/edit-time-log/:timeLogId',
views: {
'tab-logs': {
templateUrl: 'templates/logs/edit-time-log.html',
controller: 'EditTimeLogCtrl'
}
},
resolve: {
timeLog: function(config, $stateParams, DailyLog) {
return DailyLog.get({id: $stateParams.timeLogId});
},
}
})
})
This really goes down to vanilla Javascript. The resolves are objects. Just define them as a single object somewhere above and pass it to the resolve property each time.
.config(['$stateProvider',function($stateProvider) {
var timeLogResolve = {
timeLog: ['config','$stateParams','DailyLog',function(config, $stateParams, DailyLog) {
return DailyLog.get({id: $stateParams.timeLogId});
}]
};
$stateProvider
.state('tab.edit-log-summary', {
url: '/logs/edit-log-summary/:timeLogId',
views: {
'tab-logs': {
templateUrl: 'templates/logs/edit-log-summary.html',
controller: 'EditLogSummaryCtrl'
}
},
resolve: timeLogResolve,
}
})
.state('tab.edit-time-log', {
url: '/logs/edit-time-log/:timeLogId',
views: {
'tab-logs': {
templateUrl: 'templates/logs/edit-time-log.html',
controller: 'EditTimeLogCtrl'
}
},
resolve: timeLogResolve,
}
})
}])
One suggestion- use inline array notation for providing dependencies. This helps protect your code from breaking if you minify it. I did that myself in the demo above, but I leave it to your discretion to keep it.
When I uglify webpack bundle, routing stops work without any error message or log message. I am using oclazyload to lazy load.
Route.js
module.exports = function(app) {
var routeConfig = function($stateProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/dashboard/dashboard.min.html',
title: 'Home',
ncyBreadcrumb: {
label: 'Home'
}
})
.state('organizationStructure', {
url: '/organizationStructure',
templateUrl: 'app/admin/organizationStructure/manageHierarchy/manageHierarchyShell.min.html',
'abstract': true,
ncyBreadcrumb: {
skip: true
},
resolve: ['$q', '$ocLazyLoad', function($q, $ocLazyLoad) {
var deferred = $q.defer();
require.ensure([], function() {
var mod = require('./organizationStructure.module.js');
$ocLazyLoad.load({
name: 'app.organizationStructure'
});
deferred.resolve(mod.controller);
});
return deferred.promise;
}]
})
.state('organizationStructure.organization', {
url: '/organization',
templateUrl: 'app/admin/organizationStructure/manageHierarchy/organization/index.min.html',
controller: 'ManageOrganization',
controllerAs: 'vm',
title: 'Manage Organization',
ncyBreadcrumb: {
label: 'Manage Organization',
parent: 'home'
}
});
}
app.config(routeConfig);
return routeConfig;
};
Module.js
var app = angular.module('app', [
'ui.router',
'restangular',
'ui.bootstrap',
'ncy-angular-breadcrumb',
'oc.lazyLoad'
]);
Base Route
require('./app.route.js')(app);
When I minify the bundle, app routing stops working. Otherwise it works fine. Please provide me a solution. Also I am using ngAnnotate. Dependencies are injected safely in minified file.
While doing minification you should for array annotation of DI.
You are not using angular di array notation inside you app.js, you need to do below changes.
From
app.config(routeConfig);
To
app.config(['$stateProvider', routeConfig]);
For more Information Refer this SO Answer
You're using the latest version of ui-router, which has a newer and slightly different way of handling the resolve block. It takes an object map.
Try this:
resolve: {
foo: ['$q', '$ocLazyLoad', function($q, $ocLazyLoad) {
var deferred = $q.defer();
require.ensure([], function() {
var mod = require('./organizationStructure.module.js');
$ocLazyLoad.load({
name: 'app.organizationStructure'
});
deferred.resolve(mod.controller);
});
return deferred.promise;
}]
}
Here is the ui-router API doc for this: https://github.com/angular-ui/ui-router/wiki#resolve
I'm losing my mind trying to figure out why the following code produces an Unknown Provider error "geonameProvider <- geoname <- country"
var cacRouteViewMod = angular.module('cacRouteViewMod', ['ngRoute', 'cacLib']);
cacRouteViewMod.config(['$routeProvider', function($routeProvider, $routeParams) {
$routeProvider
.when('/countries/:country/capital', {
templateUrl: 'countries/country.html',
controller: 'countryDetailCtrl',
resolve: {
geoname: ['$route', 'getGeoname', function($route, getGeoname) {
return getGeoname($route.current.params.country);
}],
country: ['getCountry', 'geoname', function(getCountry, geoname) {
return getCountry(geoname.countryCode);
}],
neighbors: ['$route', 'getNeighbors', function($route, getNeighbors) {
return getNeighbors($route.current.params.country);
}]
}
})
});
I've seen some codes where almost identical code is given as a working example. Like this other stackoverflow post (Angular JS resolve in a resolve).
And this article (https://medium.com/opinionated-angularjs/advanced-routing-and-resolves-a2fcbf874a1c).
Why won't mine work?
I believe it's because you are using ngRoute (the native routing module in AngularJS) instead of ui-routeur (the module referred in your articles)
Try using ui-router instead, it should looks like:
.state('countries', {
url: "/countries/:country/capital",
templateUrl: 'countries/country.html',
controller: 'countryDetailCtrl',
resolve: {
geoname: ['$route', 'getGeoname', function($route, getGeoname) {
return getGeoname($route.current.params.country);
}],
country: ['getCountry', 'geoname', function(getCountry, geoname) {
return getCountry(geoname.countryCode);
}],
neighbors: ['$route', 'getNeighbors', function($route, getNeighbors) {
return getNeighbors($route.current.params.country);
}]
})
});
And inject it as a dependency :
var cacRouteViewMod = angular.module('cacRouteViewMod', ['ui-router', 'cacLib']);
I have got a ui -router state here
var AccountParentState = {
url: "/Account",
views: accountrootview,
stickA: true,
},
AccountAddState = {
url: "/add",
views: addaccountview,
controller: "account-controller",
resolve: {
Name: function () {
return "Joydeep";
}
}
};
$stateProvider
.state('account', AccountParentState)
.state("account.add", AccountAddState)
And this is my controller :
angular.module('ngApp').controller('account-controller', ['$scope', '$state', "account", "plugin-factory", "Name", function ($scope
, $state
, account
, plugins, Name) {
console.log(Name);
}]);
When I am trying to resolve the Name within the account-controller . Its throwing the error as :
Unknown provider: NameProvider <- Name <- account-controller
My question is how to resolve this situation . Or resolve the data within the ui-router state using resolve property .
To help you to see the issue, I created working plunker, which does use similar definition to the above states:
var AccountParentState = {
url: "/Account",
views: { '' :
{ template: 'Account state <hr/><div ui-view=""></div>',} },
stickA: true,
},
AccountAddState = {
url: "/add",
//views: addaccountview,
templateUrl: 'tpl.html',
controller: "account-controller",
resolve: {
Name: function() {
return "Joydeep";
}
}
};
$stateProvider
.state('account', AccountParentState)
.state("account.add", AccountAddState)
Factories and controller:
.factory('account', function(){return {}})
.factory('plugin-factory', function(){return {}})
.controller('account-controller',
['$scope', '$state', "account", "plugin-factory", "Name"
, function($scope, $state, account, plugins, Name) {
console.log(Name);
}
])
And that is working, because controller was instantiated by the UI-Router, as a part of the state transition.
If, on the other hand, we will extend that example with this (see forked broken version) line in the index.html (outside of the state def)
<div ng-controller="account-controller"></div>
<div ui-view=""></div>
The issue will appear. Why? Because now the controller is not managed by the UI-Router. It is not injected by its infrastructure, not provided with configured value 'Name'. It is "plain angular" style..
Check the working solution here and the broken here