pass data without adding into url - angularjs

$stateProvider.state('academicYearCatalogue', {
url: '/academicYearCatalogue/:programKey',
templateUrl: 'app-ace/academicYearCatalogue/views/academicYearCatalogue-detail.tpl.html',
controller: 'AcademicYearCatalogueDetailCtrl as AcademicYearCatalogueDetailCtrlVM',
resolve: {
academicYearList: ['AcademicYearService', '$stateParams',
function (AcademicYearService, $stateParams) {
var obj = {
programKey: $stateParams.programKey,
}
return AcademicYearService.getAllYear(obj)
.$promise.then(function (result) {
return result.data;
});
}]
}
});
i want to pass data between controllers via ui-router v 0.2.8 but don't want to add to url, how do i achieve this?
this programkey is coming from some controller and i want to use this in resolve but not with url.how do i achieve this.
angular js version is 1.2.20

Using params property of state you can pass the data as given below
params: {
user_desisred_params_name: null,
}
So the complete code is given below-
$stateProvider.state('academicYearCatalogue',
{ url: '/academicYearCatalogue',
templateUrl: 'app-ace/academicYearCatalogue/views/academicYearCatalogue-detail.tpl.html',
controller: 'AcademicYearCatalogueDetailCtrl as AcademicYearCatalogueDetailCtrlVM',
resolve: {
academicYearList: ['AcademicYearService', '$stateParams',
function (AcademicYearService, $stateParams) {
var obj = {
programKey: $stateParams.programKey,
}
return AcademicYearService.getAllYear(obj)
.$promise.then(function (result) {
return result.data;
});
}]
},
params:{
yourKey : programKey
}
});

Related

How to inject $stateParams into state resolve

I've been working on some code for a project and have run into a problem with using $stateParams. I am trying to inject a item name into my service through a resolve but it keeps coming up with undefined. I realized I need $stateParams to define it but I can't seem to inject $stateParams into the service. Here is my code and the error, thank you in advance.
Error
Uncaught Error: [$injector:modulerr]
http://errors.angularjs.org/1.6.5/$injector/modulerr?p0=MenuAppX&p1=ReferenceError%3A%20%24stateParams%20is%20not%20defined%0A%20%20%20%20at%20RoutesConfig%20(http%3A%2F%2Flocalhost%3A3000%2Fsrc%2Froutes.js%3A30%3A14)%0A%20%20%20%20at%20Object.invoke%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A44%3A357)%0A%20%20%20%20at%20d%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A42%3A237)%0A%20%20%20%20at%20http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A42%3A376%0A%20%20%20%20at%20p%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A8%3A7)%0A%20%20%20%20at%20g%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A42%3A138)%0A%20%20%20%20at%20gb%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A46%3A251)%0A%20%20%20%20at%20c%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A22%3A19)%0A%20%20%20%20at%20Uc%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A22%3A332)%0A%20%20%20%20at%20xe%20(http%3A%2F%2Flocalhost%3A3000%2Flib%2Fangular.min.js%3A21%3A1)
at angular.min.js:7
at angular.min.js:43
at p (angular.min.js:8)
at g (angular.min.js:42)
at gb (angular.min.js:46)
at c (angular.min.js:22)
at Uc (angular.min.js:22)
at xe (angular.min.js:21)
at angular.min.js:333
at HTMLDocument.b (angular.min.js:38)
State
.state('items', {
url: '/menuItems/{itemId}',
templateUrl: 'src/MenuApp/template/items.template.html',
params: {$stateParams, itemId: null},
controller: 'itemsXController as itemsX',
resolve: {
itemsResult: ['MenuDataService, $stateParams', function
(MenuDataService, itemId, $stateParams) {
return MenuDataService.getItemsForCategory($stateParams.itemId);
}]
}
})
Service
(function () {
'use strict';
angular.module('data')
.service('MenuDataService', MenuDataService)
.constant('categoryBasePath', "https://davids-
restaurant.herokuapp.com/menu_items.json?category=");
MenuDataService.$inject = ['$http', '$q', '$timeout','categoryBasePath'];
function MenuDataService($http, $q, $timeout, categoryBasePath) {
var service = this;
service.getAllCategory = function() {
var deferred = $q.defer();
var categoriesResult = $http({
method: "GET",
url: ('https://davids-restaurant.herokuapp.com/categories.json'),
});
$timeout(function () {
deferred.resolve(categoriesResult);
}, 800);
return deferred.promise;
}
service.getItemsForCategory = function(itemId) {
var deferred = $q.defer();
console.log(itemId);
var itemsResult = $http({
method: "GET",
url: ('https://davids-restaurant.herokuapp.com/menu_items.json?category=L'),
});
$timeout(function () {
deferred.resolve(itemsResult);
}, 800);
console.log(deferred.promise);
return deferred.promise;
}
};
})();
Template(the one calling the state)
<a ui-sref="items">This Page works</a>
<ol>
<li ng-repeat="item in categoriesX.categories" ui-sref="items({itemId:
categoriesX.categories[$index].short_name})">
{{ categoriesX.categories[$index].name }}
</li>
</ol>
remove itemid from the resolve function
change this
resolve: {
itemsResult: ['MenuDataService, $stateParams', function
(MenuDataService, itemId, $stateParams) {
return MenuDataService.getItemsForCategory($stateParams.itemId);
}]
}
to this
resolve: {
itemsResult: ['MenuDataService, $stateParams', function
(MenuDataService, $stateParams) {
return MenuDataService.getItemsForCategory($stateParams.itemId);
}]
}
.state('items', {
url: '/menuItems/{itemId}',
templateUrl: 'src/MenuApp/template/items.template.html',
params: { itemId: null},
controller: 'itemsXController as itemsX',
resolve: {
itemsResult: ['MenuDataService, $stateParams', function
(MenuDataService, itemId, $stateParams) {
return MenuDataService.getItemsForCategory($stateParams.itemId);
}]
}
})

Bad timing or order of functions with resolves on Ui-Router

I have an app where my main state makes a resolve makes an http call and fetches an array.
Then, the child array is supposed to display one object from this array, but it seems that the variables from the controller are defined too early and don't get updated properly, so the child comes out empty.
I've tried it without http call (var array = [array]), and it works fine, but not with the http call.
Any tips on how to fix this?
Here's the controllers:
.controller('appCtrl',['$scope', 'SearchService','fair', function($scope, SearchService, fair){
$scope.data = SearchService;
$scope.datafairs = $scope.data.flatexhibitors;
console.log($scope.datafairs);
}])
.controller('ChildController',['$scope', 'exhibitor', '$filter', function($scope, exhibitor, $filter){
$scope.$watch(function() { return $scope.fair; }, function(newVal) {
$scope.fairs = newVal;
console.log($scope.fairs);
$scope.chosenexhibitor = $filter("filter")($scope.fairs, {'slug':exhibitor}, true);
}, true);
}])
The service:
.factory("SearchService", function($http) {
var service = {
flatexhibitors : [],
datafairs : [],
getAllExhibitors : function (wop) {
var searchindex = wop;
console.log(searchindex);
var url = '../register/backend/databaseconnect/getexhibitors.php';
var config = {
params: {
search: searchindex
},
cache:true
};
$http.get(url, config).then(function (data) {
service.datafairs = data.data.rows;
for (var i in service.datafairs) {
service.flatexhibitors.push(service.datafairs[i].doc);
};
return service.flatexhibitors;
});
}
}
return service;
})
And the states:
.config(function($stateProvider) {
$stateProvider.state('berliner', {
url: '/berlinerliste',
params : {search: 'Berliner 2017'},
resolve: {
fair: function(SearchService, $stateParams) {
return SearchService.getAllExhibitors($stateParams.search);
}
},
views: {
'header': {
templateUrl: 'header.htm'
},
'main':{
templateUrl: 'bl2017.htm',
controller: 'appCtrl'
}
}
})
.state('berliner.exhibitor', {
url: '/{id}',
resolve: {
exhibitor: function($stateParams) {
var slug = $stateParams.id;
return slug;
}
},
views: {
'header': {
templateUrl: 'header.htm'
},
'wop':{
templateUrl: 'exhibitor.htm',
controller: 'ChildController'
}
}
})
})
I've managed to replicate the issue in a Plunkr.
Change the getAllExhibitors to return a promise like below:
getAllExhibitors : function (wop) {
var searchindex = wop;
console.log(searchindex);
var url = '../register/backend/databaseconnect/getexhibitors.php';
var config = {
params: {
search: searchindex
},
cache:true
};
return $http.get(url, config).then(function (data) {
service.datafairs = data.data.rows;
for (var i in service.datafairs) {
service.flatexhibitors.push(service.datafairs[i].doc);
};
return service.flatexhibitors;
});
}

Child View/Route that Resolves from Different Service than Parent

I'm having an issue loading a child view/route while resolving a GET from a different service from the parent view/route.
Within the parent view, each ion-item links to /#/tab/categories/{{ category.listing_category_id }}
When clicked the URL populates (for a flash) with the correct category ID, the child's service successfully receives the category ID, runs the subsequent GET request & returns the data as a promise...that all works as intended. The issue is that the child view/route never loads. All help/guidance is very much appreciated.
Parent
angular.module('rainbowPages.tab.categories', [])
.config(function($stateProvider, $urlRouterProvider) {
// UI Router
$stateProvider.state('tab.categories', {
url: '/categories',
views: {
'tab-categories': {
templateUrl: 'views/tab-categories/tab-categories.html',
controller: 'CategoriesCtrl'
}
}
});
// otherwise
$urlRouterProvider.otherwise('/tab/categories');
})
.factory('CategoriesService', function($resource) {
var remoteCategoriesURL = 'http://104.167.104.163:7000/api/v1/categories',
categoriesService = $resource(remoteCategoriesURL, {}, {
getAll: {
method: 'GET',
isArray: true
}
});
return categoriesService;
})
.controller('CategoriesCtrl', function($scope, CategoriesService) {
$scope.categories = CategoriesService.getAll();
});
Child
angular.module('rainbowPages.tab.categories.detail', [])
.config(function($stateProvider, $urlRouterProvider) {
// UI Router
$stateProvider.state('tab.category-detail', {
url: '/categories/:listing_category_id',
views: {
'tab-categories': {
templateUrl: 'views/category-detail/category-detail.html',
controller: 'categoryDetailCtrl'
}
},
resolve: {
listings: function($stateParams, CategoryDetailService) {
// bind data to listing
return CategoryDetailService($stateParams.listing_category_id);
}
}
});
})
.factory('CategoryDetailService', function($resource) {
var remoteCategoryURL = 'http://104.167.104.163:7000/api/v1/category/:categoryID',
categoryDetailService = $resource(remoteCategoryURL, {categoryID:'#listing_category_id'}, {
get: {
method: 'GET',
isArray: true
}
}),
getListingsInCategory = function getListingsInCategory(categoryID) {
listingsInCategory = categoryDetailService.get({categoryID:categoryID}, function(promise) {
if(promise.$resolved = true) {
console.log(promise); // how I know the promise has the correct data
return promise;
}
});
};
return getListingsInCategory;
})
.controller('categoryDetailCtrl', function($scope, listings){
console.log('listings are : ' + listings);
$scope.listings = listings;
});

Pass a request header to uriTemplate in AngularJS

I have this Angular code:
.state('UserTables', {
url: '/Tables',
resolve: {
auth: function resolveAuthentication(SessionService) {
return SessionService.isUser();
}
},
views: {
"containerMain": {
templateUrl: 'Views/Tables',
controller: TableController
},
}
})
And would like to pass some request header to the templateUrl call.
Anyone done something like that?
Basically I have a REST service that can generate the view I need depending on 1 header and some property's. Property's are no problem but I have no clue how to make a call to the service and wait for the result.
Tried:
views: {
"containerMain": {
template: function (SessionService, $http, $q) {
console.log('template');
var resp = SessionService.getTable($http, $q, 'Generate/Table?objectId=WfObject');
var r = '';
resp.then(function (result) {
r = result;
console.log('resp:', r);
});
console.log('r:',r);
return r;
}
I created working plunker here
To load template with custom headers, we can call do it like this (check the state 'UserTables' in the plunker):
views: {
"containerMain": {
//templateUrl: 'Views/Tables',
templateProvider: ['$http',
function ($http) {
var tplRequest = {
method: 'GET',
url: 'Generate/Table?objectId=WfObject',
headers: {
'MyHeaderKey': 'MyHeaderValue'
},
}
return $http(tplRequest)
.then(function(response) {
console.log('loaded with custom headers')
var tpl = response.data;
return tpl;
}
);
}],
controller: 'TableController'
},
}
In case, we want (and can) cache the template, we can do it like this (check the state 'UserTablesWithCache'):
views: {
"containerMain": {
//templateUrl: 'Views/Tables',
templateProvider: ['$http', '$templateCache',
function ($http, $templateCache) {
var templateName = 'Generate/Table?objectId=WfObject';
var tpl = $templateCache.get(templateName)
if(tpl){
console.log('returning from cache');
return tpl;
}
var tplRequest = {
method: 'GET',
url: templateName,
headers: {
'MyHeaderKey': 'MyHeaderValue'
},
}
return $http(tplRequest)
.then(function(response) {
console.log('loaded, placing into cache');
var tpl = response.data;
$templateCache.put(templateName, tpl)
return tpl;
}
);
}],
controller: 'TableController'
},
}
And if we would not need headers, and we could cache, it is really very easy, as documented here:
Trying to Dynamically set a templateUrl in controller based on constant
Drafted version could be: (no custom headers but effective loading and caching)
templateProvider: ['$templateRequest', function(CONFIG, $templateRequest) {
var templateName = 'Generate/Table?objectId=WfObject';
return $templateRequest(templateName);
}],
templateUrl property can also take function as value. So you can add dynamic properties to the templateUrl via there.
templateUrl : function(stateParams) {
// before returning the URL, add additional properties and send
// stateParamsargument object refers to $stateParams and you can access any url params from there.
return 'Views/Tables';
}

angularJS: I need to make an $http request and resolve it in the same function

In app.js, I resolve a ui-router thusly:
.state('edit', {
url: '/edit/:id',
templateUrl: '/ang/views/edit/editapp.html',
resolve: {
loan: function ($q, $stateParams, Loans) {
var p = $q.defer();
Loans.getLoan($stateParams.id)
.then(function (res) {
p.resolve(res);
});
return p.promise;
}
},
controller: 'EditAppController'
})
I have a Loans factory where this promise is resolved and in the EditAppController, I send the object back to the factory for further processing using
$scope.loan = Loans.makeLoan(loan.data.data);
Here is the pertinent part of my Loans Factory:
.factory('Loans', function($http){
return {
getLoan: function(id){
return $http.get('/api/loans/' + id);
},
makeLoan: function(o){
o.jwg = 'This added in make loan';
return o;
};
In the makeLoan() method, I just did something to prove to me that this work. What I NEED to do is to make another $http call to the API to get some additional data and I NEED to resolve that call within the same method (makeLoan()) so that I can add some calculations to the object within this function before giving it to the controller for the view.
Can someone explain to me how I can do this?
If you need to make 2 calls to the API and you want to retrieve just the promise of the last call, you can chain the promises. This will only return the last promise:
makeLoan: function(){
return $http.get('/api/loans/whatever').then(function(data){
return $http.get('/api/loans/whatever2/'+data.id);
});
}
Also, if I may: what you are doing here:
.state('edit', {
url: '/edit/:id',
templateUrl: '/ang/views/edit/editapp.html',
resolve: {
loan: function ($q, $stateParams, Loans) {
var p = $q.defer();
Loans.getLoan($stateParams.id)
.then(function (res) {a
p.resolve(res);
});
return p.promise;
}
},
controller: 'EditAppController'
})
It's an anti-pattern known as deferred anti-paattern, a better way to do it would be:
.state('edit', {
url: '/edit/:id',
templateUrl: '/ang/views/edit/editapp.html',
resolve: {
loan: function ($stateParams, Loans) {
return Loans.getLoan($stateParams.id);
}
},
controller: 'EditAppController'
})

Resources