i have a module with 2 routes:
admin.config(["$routeProvider", function ($routeProvider) {
$routeProvider.when('/admin/companies', {
templateUrl: "modules/" + 'admin/partials/adminCompanies.html',
controller: AdminCompaniesController,
resolve: {
'user': function (SecurityService) {
return SecurityService.authorize('admin');
}
}
});
}]);
admin.config(["$routeProvider", function ($routeProvider) {
$routeProvider.when('/admin/works/:id', {
templateUrl: "modules/" + 'admin/partials/adminWorks.html',
controller: AdminWorksController,
resolve: {
'user': function (SecurityService) {
return SecurityService.authorize('admin');
}
}
});
}]);
In AdminCompaniesController i have a function for go to /admin/works/:id but i need to send one object from $scope in AdminCompaniesController to $scope in AdminWorksController, How can i do it this? I dont have idea..
Services are the go-to for passing data between controllers. Create a service and assign the data in your companies controller, then have your works controller read the data from that same service. There are countless examples of how to do this, but the example that comes to mind is here: How do I use $rootScope in Angular to store variables?.
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 am a bit confused. I am trying to get my resolve data in my controller. I read about these (and more) solutions, but can not get it working. It is all about the "spages".
http://jsfiddle.net/Avb4U/1/
http://www.jvandemo.com/how-to-resolve-angularjs-resources-with-ui-router/#
Angularjs resolve with controller as string
I hope this is not a duplicate question, because nothing did work for me from these solutions.
This is (part of all states) my state:
.state('root.search', {
url: '/search/:searchterm',
onEnter: ['$rootScope', function($rootScope) {
$rootScope.bodyclass = 'search';
}],
resolve : {
spages: ['$stateParams', 'SearchPages', function($stateParams, SearchPages) {
return SearchPages.get({'searchterm': $stateParams.searchterm});
}]
},
controller: 'searchCtrl',
views: {
'#': {
templateUrl: templateUrlFunction('search')
}
}
})
This is part of my controller:
app.controller('searchCtrl', ['$scope', 'spages', function($scope, spages) {
// spages should be already resolved and injected here
}
And this is my factory for the searchpages:
app.factory('SearchPages', ['$resource', function($resource) {
return $resource(null, {},
{
get: {
method: 'GET',
url: '/json/search/get/searchterm/:searchterm',
params: {searchterm: '#searchterm'}
}
});
}]);
Asfar as i do understand, spages should be resolved and injected in the controller now. But it is not.
The error i get is:
Error: [$injector:unpr] Unknown provider: spagesProvider <- spages
What do i do wrong? I am still learning...
Ok, what i did not realize is that i also have a controller in my template.
And i read: "You only need to specify controller once, in app.js. The second one, in the html code, is instantiated by the ngController directive, which does not know about `resolve', so it throws an exception."
Change your controller dependency from searchpages to SearchPages.
app.controller('searchCtrl', ['$scope', 'SearchPages', function($scope, searchpages) {
// searchpages should be already resolved and injected here
}
Following the MVC pattern, one controller should be able to handle multiple views in AngularJS.
E.g. I have one view for showing all users and one for creating a new user. My $routeProvider (excerpt) looks like this:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/showusers', {
templateUrl: 'partials/showusers.html',
controller: 'userController'
}).
when('/createuser', {
templateUrl: 'partials/showusers.html',
controller: 'userController'
})
}]);
Both views share several methods such as retrieving all user attributes. These shared methods are accessed through a factory.
The userController (excerpt) currently looks like this where Users is a factory:
angular.module('supportModule').
controller('userController', function($scope, Users) {
var init = function(){
$scope.users = Users.getAll();
$scope.attributes = Users.getAttributes();
}
init();
})
The problem is: I don't need to request Users.getAll(); when I'm on the createuser view.
Of course, I could easily parse the route by using $location, the $routeProvider or pure JS and then conditonally call methods - but I figure there is a more elegant and efficient way in Angular :)
Something like in typical MVC frameworks where one controller has many actions - one for each view.
So my question:
How to elegantly call methods based on the view in a controller which controls more than one view?
You could use resolve: when setup $routeProvider to pass values to a controller depending on the matched route.
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/showusers', {
templateUrl: 'partials/showusers.html',
controller: 'userController',
resolve: {
ctrlOptions: function () {
return {
getAllUsers: true,
};
}
}
}).
when('/createuser', {
templateUrl: 'partials/showusers.html',
controller: 'userController',
resolve: {
ctrlOptions: function () {
return {
getAllUsers: false,
};
}
}
})
}]);
and then in the controller, you can inject item specified in resolve: like this:
app.controller('userController', function ($scope, Users, ctrlOptions) {
var init = function () {
if (ctrlOptions.getAllUsers) {
$scope.users = Users.getAll();
}
$scope.attributes = Users.getAttributes();
};
init();
});
Hope this helps.
I need to build a User that can be the resut of different REST API call (each way comes from a specific route).
Let's say for this example that we can visit:
http://myapp/#user/:pseudo
http://myapp/#user/:user_id
angular.module('Test').config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/user/:pseudo', {
templateUrl: 'views/user.html',
controller: 'userFromPseudoCtrl'
}).
when('/user/:user_id', {
templateUrl: 'views/user.html',
controller: 'userFromIdCtrl'
}).
otherwise({
redirectTo: '/'
});
}
]);
then, i have 3 different controllers:
userFromPseudoCtrl
userFromIdCtrl
userCtrl (To control the view)
angular.module('Test').controller('userFromPseudoCtrl', function($User, $http) {
$http.get('/getUserFromPseudo/test')
.success(function(User) {
$User.set(User);
});
});
angular.module('Test').controller('userFromIdCtrl', function($User, $http) {
$http.get('/getUserFromId/test')
.success(function(User) {
$User.set(User);
});
});
angular.module('Test').controller('userCtrl', function($scope, $User) {
$scope.User = $User;
});
This way is not good because the userCtrl is called before the $http callback (from the router's controllers), so the User is actually empty into the page (i was hopping it will be automatically updated).
Before i try to manage with it (using $rootScope.$apply()), i am wondering what is the more optimize way to do this kind of process (loading datas from router's controller then display it).
Do you use as many controllers as i do ? Do you process these REST APIs calls in the same controller that "bind" your view ? I am interesting to know !
When you define your routes you can define an additional value named resolve which is an object where each field is a promise that when resolved will be injected into your controller:
Route Definition:
when('/user/:pseudo', {
templateUrl: 'views/user.html',
controller: 'userFromPseudoCtrl'
resolve: {dataNeeded: userPseudoService.getUserData()});
Service (new):
angular.module('Test').service('userPseudoService', function($http){
return $http.get('/getUserFromPseudo/test');
});
Controller:
angular.module('Test').controller('userFromPseudoCtrl', function(dataNeeded){});
The route will not change until the promise is resolved.
I want my app to fetch data from a server API, lets say I have the following API /orders , /users. Basically I just want to display the json I get from the server in a table. I am using ng-table directive for that purpose. So, in terms of components I have :
Services - both services do the same thing - go to an API and fetch JSON
Views - same view for both of the APIs, just display different data
Controllers - both fetch data from the service and display it in the table view.
So the way I see it, they all do the same thing with very minor adjustments. What I would like to do is
angular.module('admin').config(function ($routeProvider, $locationProvider) {
// same template and controller for both
$routeProvider.
when('/users', {
templateUrl: '/partials/table.html',
controllers: '/js/controllers/table.js
}).
when('/orders', {
templateUrl: '/partials/table.html',
controllers: '/js/controllers/table.js'
});
});
And in my service
factory('AdminService', ['$resource', function($resource) {
// somehow I want to inject the right endpoint, depending on the route
return $resource( '/:endpoint',
{ }, {} );
}]);
And in my table controller as well, I want to be able to know what to pass to the service
I could of course use separate controllers and services for each API endpoint it just seems like a wasteful duplication of code that does 99% the same thing
Is this possible ?
How do I wire everything together ?
If you want separate routes, but the same controller, but with some options, you can use the resolve option in the route definition to pass some options:
$routeProvider.
when('/users', {
templateUrl: '/partials/table.html',
controller: 'TableController',
resolve: {
'option1': function() {
return 'val1'
},
'option2': function() {
return 'val2'
}
}
}).
when('/orders', {
templateUrl: '/partials/table.html',
controller: 'TableController',
resolve: {
'option1': function() {
return 'val3'
},
'option2': function() {
return 'val4'
}
}
});
Then the controller in both cases will be injected with "option1" and "option2", which can be used to customise its behaviour:
app.controller('TableController', function($scope, option1, option2) {
// Do something with option1 or option1
});
From the resolve object functions, you could return a $resource object, or even return a promise that will be resolved with some data before the route is displayed. You can see the docs for $routeProvider for details.
Edit: For the resource, you could write a configurable factory like:
app.factory('MyResource', function($resource) {
return function(endpoint) {
return $resource('/' + endpoint);
}
});
And then use it in the controller:
app.controller('TableController', function($scope, MyResource, endpoint) {
var currentResource = MyResource(endpoint);
currentResource.query(); // Whatever you want to do with the $resource;
}
assuming that "endpoint" was was one of the options added in the resolve, so something like
when('/orders', {
templateUrl: '/partials/table.html',
controller: 'TableController',
resolve: {
'endpoint': function() {
return '/orders'
}