I've got factory with some return on open modal window
Example:
openModal: function (urn, id, templateId, controller) {
$http({
method: 'GET',
url: urn
}).success(function (data, $scope) {
$("#" + id).append($compile(data)($scope));
modalInstance = $uibModal.open({
templateUrl: templateId,
controller: controller,
backdrop: 'static',
keyboard: false
});
}).error(function () {
alert("error");
return null;
});
document.getElementById('main').classList.add("blur");
},
After this function and view append to DOM, I want to call another function
from another service witch i inject to thouse openModalfactory.
Example:
$map.autocomplite('wizardsearch');
$map.getAutoUserLocationPath();
Could you explain how I must do this through $q?
Thank you for you answer.
deferring should make the function return a promise which you can use to do something when this function is finished
look to the the following code
openModal: function (urn, id, templateId, controller,$q) {
var def = $q.defer();
$http({
method: 'GET',
url: urn
}).success(function (data, $scope) {
def.resolve(data);
$("#" + id).append($compile(data)($scope));
modalInstance = $uibModal.open({
templateUrl: templateId,
controller: controller,
backdrop: 'static',
keyboard: false
});
}).error(function (err) {
def.reject(err)
alert("error");
});
document.getElementById('main').classList.add("blur");
return def.promise;
}
to use it call it like :
openModel().then(function(){
//do what you want here
})
I imagine that you want something like this :
let deferred = this.$q.defer();
let promises = [];
promises.push(service.something);
this.$q.all(promises).then(/*Do something*/);
return deferred.promise;
Related
I really new with AngularJs and I'm trying to create multiple routes with different $http requests. My problem start when the route change and the page content show later.
I figure it out in some way and i think its not the right way.
Hope someone can tell me if there is a better way.
Note: AngularJs version: 1.6 | Using ui router
main.js
var asTwl = angular.module('asTwl', ['ui.router']);
asTwl.controller('generals', function($scope, $http, $timeout){
$scope.pageLoader = false;
$scope.getPageData = function(path, postData, obj){
$scope.pageLoader = true;
$http({
method: 'post',
url: path,
data: postData,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.then(function(response) {
if (response.data) {
$scope.data[obj] = JSON.parse(response.data);
$timeout(function(){
$scope.pageLoader = false;
}, 100)
}
})
.catch(function(e) {
new Error('Error: ', e);
throw e;
})
}
});
asTwl.controller('homePage', function($scope, $http){
var postData = {
//data...
}
$scope.getPageData('path', postData, 'home')
})
asTwl.controller('singlePage', function($scope, $http, $stateParams){
var postData = $stateParams;
$scope.getPageData('path', postData, 'page')
})
asTwl.controller('categoryPage', function($scope, $http, $stateParams){
var postData = $stateParams;
$scope.getPageData('path', postData, 'category')
})
asTwl.config(function($stateProvider, $urlRouterProvider, $locationProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl : 'templates/pages/home.html',
controller : 'homePage'
})
.state('info', {
url: '/info/:id',
templateUrl : 'templates/pages/info.html',
controller : 'singlePage'
})
.state('category', {
url: '/category/:type/:id',
templateUrl : 'templates/pages/category.html',
controller : 'categoryPage'
})
});
Thank you!
First, wrap your $http calls to services. Next,try to use resolve https://github.com/angular-ui/ui-router/wiki#resolve
Edit
Ok, example is here (without wrapping to service):
$stateProvider
.state('home', {
url: '/',
templateUrl : 'templates/pages/home.html',
controller : 'homePage',
resolve: {
routeData: function($http){
return $http({
method: 'post',
url: 'path',
data: postData /* your POST data - i don't know what is it for your code*/,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
}
}
})
.state('info', {
url: '/info/:id',
templateUrl : 'templates/pages/info.html',
controller : 'singlePage'
})
.state('category', {
url: '/category/:type/:id',
templateUrl : 'templates/pages/category.html',
controller : 'categoryPage'
})
And in controller:
asTwl.controller('homePage', function($scope, routeData){
$scope.someData = routeData;
})
You should first create a service which will be responsible for communicating with Server/API for playing around with data. You could include that method getPageData in that, it returns a promise object.
Service
app.service('myService', function($http){
var self = this;
self.getPageData = function(path, postData){
return $http.post(path,postData, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' });
.catch(function(e) {
new Error('Error: ', e);
throw e;
});
});
Then you could easily utilize the resolve option of state of ui-router will wait till your ajax promise gets resolved.
.state('info', {
url: '/info/:id',
templateUrl : 'templates/pages/info.html',
controller : 'singlePage',
resolve: {
getData: function(myService) {
return myService.getPageData('path', {}, 'info')
}
}
})
In a nutshell your routes have to be changed like this:
.state('category', {
resolve: {
data : ($stateParams, dataService) => dataService.getData('path', $stateParams, 'category')
},
url: '/category/:type/:id',
templateUrl : 'templates/pages/category.html',
controller : 'categoryPage'
})
And getData method should be refactored to the service (dataService)
Everytime when I make View redirect (I use href to do so) I can see that AngularJS runs GetAjaxData1, GetAjaxData2.
In the other words: instead of the single initial request to the server, I do it everytime when I make View redirection. What is wrong?
Here is my AngularJS code:
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
controller: 'UController',
templateUrl: '/Partial/View1.html'
}).when('/View2', {
controller: 'UController',
templateUrl: '/Partial/View2.html'
}).otherwise({redirectTo: '/View3'});
}]).factory('uFactory', function () {
var factory = {};
data1 = [];
data2 = [];
factory.getAjaxData1 = function () {
$.ajax({
url: url,
type: 'GET',
contentType: "application/json",
async: false,
success: function (result) {
data1 = result;
}
});
return data1;
};
factory.getAjaxData2 = function () {
$.ajax({
url: url,
type: 'GET',
contentType: "application/json",
async: false,
success: function (result) {
data2 = result;
}
});
return data2;
}
};
var controllers = {};
controllers.uController = function ($scope, $location, uFactory) {
$scope.data1 = uFactory.getAjaxData1();
$scope.data2 = uFactory.getAjaxData2();
};
You definitely have to read about $http and ng-resource library and
try more angular way in your application and you also should
understand that ajax request is always asynchronous, and try to
understand promise pattern.
Technically - what you need is a caching - no matter how you are going to implement this - you need to make a single call to the API and the to cache variable.
I don't like idea of usage $.ajax, but it can look like this:
angular.module('myApp').config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
controller: 'UController',
templateUrl: '/Partial/View1.html'
}).when('/View2', {
controller: 'UController',
templateUrl: '/Partial/View2.html'
}).otherwise({redirectTo: '/View3'});
}]).factory('uFactory', function () {
return {
getFirstPromise: function () {
if (!this.$$firstPromise) {
this.$$firstPromise = $.ajax({
url: url,
type: 'GET',
contentType: "application/json"
}).then(function (data) {
window.data1 = data;
});
}
return this.$$firstPromise;
}
... //some other code
}
});
var controllers = {
uController: function ($scope, $location, uFactory) {
uFactory.getFirstPromise().then(function (data) {
$scope.data1 = data;
});
// same for other data - and don't try to make ajax requests synhronous ;-)
}
};
Controllers are not singletons. So your "UController" is created everytime your view changes. I assume that the factory is used inside this controller. See: What is the lifecycle of an AngularJS Controller?
Inside homeController file I have function
$scope.MyFunction = function () {
$http({
method: 'POST',
url: '/SomeUrl/ActionToDo',
data: { id: 1001 },
}).success(function (response) {
if (response.Status == 1) {
//success to do
}
$modal.open({
controller: 'modalController',
templateUrl: '/app/views/modalTemplate.html',
resolve: {
myData: function () {
return response;
}
}
});
} else {
alert(error);
}
}).error(function () {
alert('Error!');
});
}
Where I'm calling modalController to open modal window. Question is how can I pass data to this controller (modalController) from homeController in order to inject currently selected language which is available inside homeController in variable $scope.selLanguage
You can inject it into controller as resolve dependency:
$modal.open({
controller: 'modalController',
templateUrl: '/app/views/modalTemplate.html',
resolve: {
myData: function () {
return response;
},
language: $scope.selLanguage
}
});
so it will be available in controller as service
.controller('modalController', function(myData, language) {
console.log(language);
})
passed the data as locals to the modal controller using resolve.
resolve: {
myData: function () {
return response;
},
modalVar: $scope.selLanguage
}
In modalController refer that variable as it is local to that modalController controller.
angular.module('demo').controller('modalController', function ($scope, $modalInstance, modalVar) {
$scope.modalVar= modalVar;
});
Please refer this for more
we are trying to get data from service agrService with $http its working but when i reccive data to controller i am not able to access it outside that function
$scope.resource return data inside function but not outside please help.
var app = angular.module('app', ['ui.router','ngTasty']);
app.config(['$urlRouterProvider', '$stateProvider',function($urlRouterProvider, $stateProvider, $routeProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'templates/home.html',
controller: function($scope, $http, $location, agrService) {
agrService.bannerSlides().then(function(data) {
//its working here
$scope.resource = data;
}, function(error) {
// do something else
});
I NEED TO ACCCESS DATA HERE CAN ANY BODY HELP
console.log($scope.resource);
}
});
}]);
app.service('agrService', function($q, $http) {this.bannerSlides = function() {
var dataUrl = 'http://WWW.EXP.COM/codeIgniter_ver/main/home';
var ret = $q.defer();
$http({
method: 'GET',
dataType: "json",
url: dataUrl
})
.success(function(data, status, headers, config) {
ret.resolve(data);
}).error(function(data, status, headers, config) {
ret.reject("Niente, Nada, Caput");
});
return ret.promise;
};
});
My suggestion would be to rethink the logic a bit. You want to do something with the data after you receive it, so why not make a function that you call once the data is received?
You'll never be able to access the resource data in that console log, simply because $http is an async call, and no matter if you return a promise or not, it's simply not ready at that point.
However, if you use it in a template or elsewhere that uses angular's double binding, it will work just fine.
To fix your issue, you can define a function with what happens after that service call and simply call it from the success callback:
agrService.bannerSlides().then(function(data) {
//its working here
$scope.resource = data;
myAfterFunction(); // <--- here
}, function(error) {
// do something else
});
and the function can be:
function myAfterFunction() {
console.log($scope.resource);
}
And btw. your service is an example of deferred antipattern, you can simply do this:
app.service('agrService', function($q, $http) {this.bannerSlides = function() {
var dataUrl = 'http://WWW.EXP.COM/codeIgniter_ver/main/home';
return $http({
method: 'GET',
dataType: "json",
url: dataUrl
})
};
});
I'm trying to use angular promise using $q that is wrapped in 'service' and call it from my controller.
Here is the code:
var myController = function ($scope, myService) {
$scope.doSomething = function (c, $event) {
$event.preventDefault();
myService.method1(c).then(function (rslt) {
alert(rslt);
}, function (err) {
alert(err);
}).then(function () {
//clean up
});
};
};
var myApp = angular.module('myApp', [])
.factory('myService', function($q) {
function _method1(c) {
var dfr = $q.defer();
var dt = { sc: c };
$.ajax({
type: "POST",
url: "mypage.aspx/mymethod",
data: JSON.stringify(dt),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function () {
dfr.resolve('actions sucess');
},
error: function (msg) {
dfr.reject(msg);
}
});
return dfr.promise;
}
return { method1: _method1 };
}).controller('myController', myController);
The problem is that ' alert(rslt);' piece of code is never executed.
Service is called and data is updated but first 'then' function is not reached on first click.
What am I doing wrong?
Any help appreciated.
I would recoomend you to use $http and $resource instead of $.ajax
Heres an example of $http
myApp.factory('MyService',
[
'$http',
'$q',
'$resource',
function (
$http,
$q,
$resource
) {
return {
doSomething : function (somedata) {
var deferred = $q.defer();
$http({ method: 'POST', url: '"mypage.aspx/mymethod"', data: somedata }).
success(function (data, status, headers, config) {
deferred.resolve(true);
}).
error(function (data, status, headers, config) {
deferred.resolve(false);
});
return deferred.promise;
}
};
}]);
Just add the dependency to $rootScope and call $rootScope.$apply() in both callbacks from $.ajax():
success: function () {
dfr.resolve('actions sucess');
$rootScope.$apply();
}, ...
But better yet, use Angular's $http service.