I am totally newbie to AngularJs.
I have pretty good example of ngClick which is calling a Facebook function.
I would like to change it and programmatically to call registerWithFacebook function after my controller will be ready. What is the way for it?
Here is the sample: http://jsfiddle.net/IgorMinar/Hxbqd/5/
angular.module('HomePageModule', []).service('facebookConnect', function($rootScope) {
this.askFacebookForAuthentication = function(fail, success) {
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', function() { $rootScope.$apply(success) });
} else {
$rootScope.$apply(function() {
fail('User cancelled login or did not fully authorize.')
});
}
});
}
});
function ConnectCtrl(facebookConnect, $scope, $resource) {
$scope.user = {}
$scope.error = null;
$scope.registerWithFacebook = function() {
facebookConnect.askFacebookForAuthentication(
function(reason) { // fail
$scope.error = reason;
}, function(user) { // success
$scope.user = user
});
}
// Tried this but no success
// $scope.registerWithFacebook();
}
ConnectCtrl.$inject = ['facebookConnect', '$scope', '$resource'];
Thanks
If you want to load the FB library asynchronously, you need to let angular know after it initializes. Here is one way to do it:
http://plnkr.co/edit/YO4duxL1Mh3dwYEEpprV?p=preview
Related
I am using an initial screen(initial.html) and i want it to act as a splashscreen and then call the inappbrowser.
But inappbrowser is not opening. If i place it directly it works.
No error is also coming. The required functionality is to have a splash screen view getting redirected to inappbrowser, user will log in and upon successful login will be redirected to the view.( Individual parts are working, but when i put it inside a TimeOut function it is not working ).
Is there any better way to achieve this functionality.
controller.js
.controller('LoginCtrl', function($scope,$timeout,$rootScope,LoginService, $ionicPopup, $state,$location,$ionicPopup) {
$timeout(function(){
LoginService.loginUser().success(function(data) {
console.log(data);
$location.path('app/playlists');
}).error(function(data) {
var alertPopup = $ionicPopup.alert({
title: 'Login failed!',
template: 'Please check your credentials!'
});
});
}, 3000);
})
services.js
angular.module('starter.services', [])
.service('LoginService', function($q,$rootScope,$cordovaInAppBrowser,$http,$state,jwtHelper,$location) {
return {
loginUser: function() {
var deferred = $q.defer();
var promise = deferred.promise;
console.log("Hi Service"); // IT IS REACHING HERE THEN STUCK
$cordovaInAppBrowser.open(URL, '_self',options).then(function(event){
console.log(event);
// success
})
.catch(function(event) {
console.log(event);
// error
});
$rootScope.$on('$cordovaInAppBrowser:loadstop', function(e, event){
if(userValid){
deferred.resolve(username); }
else{
deferred.reject('Auth Failed');
}
});
//promise created outside
promise.success = function(fn) {
promise.then(fn);
return promise;
}
promise.error = function(fn) {
promise.then(null, fn);
return promise;
}
return promise;
}
});
I removed and reinstalled the inappbrowser plugin and it worked correctly. I apologize for the confusion
I am not sure what exact keywords to search for this. So I decided to ask here for help.
I think this is more a JavaScript related question rather than angular. Anyways here is my problem.
I am in a DRY situation (don't repeat yourself). I am trying to merge the two of my $http.put and $http.delete methods' success and error function under single one, because they share the same functionalities.
Here is my current code
// Delete permanenty button action
$scope.delete_donor = function(form) {
$http.delete(url)
.success(function() {
// #TODO DRY? DELETE UPDATE delete_donor update_donor
response.ipv4 = INT_TO_STR_IP(response.ipv4)
// Show deleted data to user after operation
$scope.donor.saved_data = response.saved_data
$location.path("/")
})
.error(function(response) {
$scope.donor.validation_errors = SERVER_VALIDATION_ERROR(response)
})
}
// Save changes button action
$scope.update_donor = function(form) {
var body = $scope.donor.data
delete body.ipv4
$http.put(url, body)
.success(function(response) {
// #TODO DRY? DELETE UPDATE delete_donor update_donor
response.ipv4 = INT_TO_STR_IP(response.ipv4)
// Show new updated data to user after operation
$scope.donor.saved_data = response.saved_data
$location.path("/")
})
.error(function(response) {
$scope.donor.validation_errors = SERVER_VALIDATION_ERROR(response)
})
As you can see $http.delete().success().error() and $http.put().success().error() methods are same.
I am trying to do something like
WHATSTHIS unify(response) {
WOOT .success(function(response) { // SAME CODE BODY })
WOOT .error(function(response) { // SAME CODE BODY })
}
// Delete permanenty button action
$scope.delete_donor = function(form) {
$http.delete(url)
.unify(response)
}
// Save changes button action
$scope.update_donor = function(form) {
var body = $scope.donor.data
delete body.ipv4
$http.put(url, body)
.unify(response)
I just know one way to achieve something similiar which is:
var unifySuccess = function(response) {
// DO
}
var unifySuccess = function(response) {
// DO
}
// Delete permanenty button action
$scope.delete_donor = function(form) {
$http.delete(url)
.sucesss(unifySuccess)
.error(unifyError)
But maybe there is an other clever way to do this?
Thanks for your help.
what you could do is create your own http request service that will do these functionalities and return the promise as a response
something like this
angular.module('myApp')
.service('proxyHttp', function($http) {
return function(options) {
return $http(options)
.then(
function() {
// success callback
},
function() {
// error callback
});
}
})
Update: For example
angular.module('myApp', [])
.service('proxyHttp', function($http, $q) {
return function(options) {
console.log('Run proxy http');
return $http(options)
.then(
function(response, status) {
console.log('always do this on success');
// success callback
return response;
// here we return the response or what ever you want,
// and we can continue handling it
})
.catch(function() {
console.log('we failed!');
// error callback
return $q.reject();
})
}
})
.controller('testController', function($scope, proxyHttp) {
$scope.testError = function() {
console.log('Run test error method');
proxyHttp({
url: 'http://www.google.com',
method: 'GET'
})
.then(
function() {})
.catch(function() {
console.log('we continue handling our error here...');
});
}
$scope.testSuccess = function() {
console.log('Run test success method');
proxyHttp({
url: 'http://httpbin.org/ip',
method: 'GET'
})
.then(
function(response) {
console.log('continue chaining after success for the original promise');
console.log('Response data: '
response.data.origin);
console.log('read more about pomise and chaining here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise');
})
.catch(function() {
console.log('error');
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="testController">
<button ng-click="testError()">Click Me for error!</button>
<br/>
<br/>
<button ng-click="testSuccess()">Click Me for success!</button>
</div>
</div>
Depending on your actual use case, this may end up sacrificing too much readability to be helpful, but since you asked specifically for cleverness:
function attachHttpResponseHandling(httpPromise) {
httpPromise
.success(function(response) {
response.ipv4 = INT_TO_STR_IP(response.ipv4);
// Show new updated data to user after operation
$scope.donor.saved_data = response.saved_data;
$location.path("/");
})
.error(function(response) {
$scope.donor.validation_errors = SERVER_VALIDATION_ERROR(response);
})
;
}
// Delete permanenty button action
$scope.delete_donor = function(form) {
attachHttpResponseHandling($http.delete(url));
};
// Save changes button action
$scope.update_donor = function(form) {
var body = $scope.donor.data;
delete body.ipv4;
attachHttpResponseHandling($http.put(url, body));
};
I'm going to make a mailbox with angular js so i have a service and a controller that manage the mails.
Service
app.service('mails',['$http','$interval','$rootScope',function($http,$interval,$rootScope){
var updatedData;
$interval(function(){
return $http.post('inc/get_mails.php?user='+'<?php echo $_SESSION['user']; ?>')
.success(function(response){
updatedData = response;
alert(updatedData);
$rootScope.$broadcast('got new mail!', { data: updatedData });
})
.error(function(err){console.log(err);});
},1000);
}]);
Controller
$scope.$on('got new mail!', function(event, args) {
$scope.mails = args.data;
});
but i have a problem this service does not run even 1 time. what should i do!? :(
tnx
The code in your service is not called, you have to inject your service in order to run it. But I think it's a better practice to create a method in your service to init your code, it's more explicit.
app.factory('mails',['$http','$interval','$rootScope',function($http,$interval,$rootScope){
var updatedData = [];
return {
init: init
}
function init() {
$interval(function(){
return $http.post('inc/get_mails.php?user='+'<?php echo $_SESSION['user']; ?>')
.success(function(response){
// check if their is a difference between this call and the last call
if (updatedData.length !== response.length) {
updatedData = response;
alert(updatedData);
$rootScope.$broadcast('got new mail!', { data: updatedData });
}
})
.error(function(err){console.log(err);});
},1000);
}
}]);
And then if you want to run the code :
app.controller('yourCtrl', ['mails', '$scope', function(mails, $scope) {
mails.init();
// each time you have a new mail
$scope.$on('got new mail!', function(event, args) {
$scope.mails = args.data;
});
}]);
I'm struggling for the past day with some weird situation.
What's happening is that for an http request to an API on a remote server occasionally duplicate requests are being sent.
Can anyone please provide help on how to avoid these duplicated requests?
Here is an example of a function that I use on a factory:
factory.getAllConsultedClientsLogs = function(oParams) {
var deferred = $q.defer();
$http.post('url/to/api', oParams)
.success(function(response) {
deferred.resolve(response);
})
.error(function() {
deferred.reject("Error! #factory.getAllConsultedClientsLogs");
});
return deferred.promise;
};
...and an example of a function using the above indicated on a controller:
$scope.openConsultedClientsLogsModal = function(operator, date) {
if (angular.isDefined(operator) && angular.isDefined(date)) {
RrAuditingFactory.getAllConsultedClientsLogs({'operator':operator,'date':date}).then(function(promise) {
if (angular.isObject(promise) && angular.isDefined(promise.error) && promise.error == 0) {
var modalInstance = $modal.open({
templateUrl: 'path/partial',
controller: function($scope, $modalInstance, logsResult) {
$scope.logsResult = logsResult;
},
resolve: {
logsResult: function() {
return promise.result;
}
}
});
modalInstance.result.then(function() {
}, function () {
});
} else {
ErrorContext.setError(promise.errorMsg);
}
}, function(promise) {
ErrorContext.setError(promise);
});
} else {
ErrorContext.setError();
}
};
Thank you in advance.. hope that anyone could help me out...
i have faced this problem, and you can resolve it like this :
check if you have declared ng-controller twice , you need to declare it just one time
check if you have declared data-ng-click , if so , you need to replace it with ng-click
that's it
I saw your link:
$scope.fnRowCallback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
$('td:eq(4)', nRow).bind('click', function() {
$scope.$apply(function() {
$scope.openConsultedClientsLogsModal(aData.Operator, aData.LogDate);
});
});
return nRow;
};
You can unbind before doing the bind, this way you will prevent duplicates.
Try like this:
$scope.fnRowCallback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
//add this unbind to your code
$('td:eq(4)', nRow).unbind("click");
$('td:eq(4)', nRow).bind('click', function() {
$scope.$apply(function() {
$scope.openConsultedClientsLogsModal(aData.Operator, aData.LogDate);
});
});
return nRow;
};
I hope this helps.
I tend to return an object from a factory, so in your case I'd do something like:
module.factory('clientsLogs', function($q, $http) {
return {
getAllConsulted: function(oParams) {
var deferred = $q.defer();
$http.post('url/to/api', oParams)
.then(function(response) {
deferred.resolve(response);
}, function() {
deferred.reject("Error! #factory.getAllConsultedClientsLogs");
});
return deferred.promise;
}
}
});
and then in your controller something like:
module.controller('MyCtrl', function($scope, clientsLogs) {
clientLogs.getAllConsulted({}).then(function(){...})
}
Might not help you but I've never had any problems with duplicate calls doing it this way.
I'm having a recurrent problem with my angular app whereby it doesn't refresh the page after data has been added, edited or removed. So if I add a new item to a list of subjects, the new item doesn't appear on the list unless I navigate away from the page and then come back to it. I've tried using route.reload and then resetting the scope of the subjects list below. I put in an alert to see if it get fired- but the alert appears before the page redirects back to the list of subjects, which is strange as $location.path('/subjects') is two lines before it. Here's my controller:
angular.module('myApp.controllers')
.controller('SubjectEditCtrl', ['$scope', '$routeParams', 'SubjectFactory', 'SubjectsFactory', '$location', '$route',
function ($scope, $routeParams, SubjectFactory, SubjectsFactory, $location, $route) {
// callback for ng-click 'updateSubject':
$scope.updateSubject = function () {
//Performs an update to the server
SubjectFactory.update($scope.subject);
//Redirects to list of all subjects
$location.path('/subjects/');
//Should reset the scope of the subject list
$scope.subjects = SubjectsFactory.query();
//Should reload the page
$route.reload();
//For debugging- the alert appears BEFORE the redirect to list of all subjects happens
alert('route reload happening');
};
SubjectFactory.show({id: $routeParams.subjectId}).$promise.then(function(subject) {
$scope.subject = subject;
}, function(err) {
console.error(err);
});
}]);
Can anyone suggest a solution?
EDIT: Subjects Service
var app = angular.module('myApp.services');
app.factory('SubjectsFactory', function ($resource) {
return $resource('https://myapiurl.com/subjects', {}, {
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
})
});
app.factory('SubjectFactory', function ($resource) {
return $resource('https://myapiurl.com/subjects/:id', {}, {
show: { method: 'GET', isArray: false },
update: { method: 'PATCH', params: {id: '#id'} },
delete: { method: 'DELETE', params: {id: '#id'} }
})
});
Some times you need to apply changes to scope this is done by the following code:
$scope.$apply();
But this can be done only if it's not in "$digest" phase, otherwise it will throw exception. So you need to check first it's not in "$digest" phase then you can apply it. Here is the example of the code I use for safe applying changes:
safeApply: function (scope, callback) {
if (scope.$$phase != '$apply' && scope.$$phase != '$digest' &&
(!scope.$root || (scope.$root.$$phase != '$apply' && scope.$root.$$phase != '$digest'))) {
scope.$apply();
}
if (angular.isFunction(callback)) {
callback();
}
}
I can suggest next way:
You can't get data from database, after adding, you can easly push new added object to $scope.items.
Example:
$scope.add = function (newItem) {
DataService.addItem(newItem).then(function(){
$scope.items.push(newItem);
//or for removing
//$scope.items.splice($scope.items.indexOf(newItem), 1);
});
};
And adjust your factory:
addItem: function (newProject) {
$http.post('Api/Controller/Post').then(function(successResult){
...
}, function (errorResult) {
...
});
}
Item will be added in $scope.items only after success calling of server-side method.
Changing the structure of the requests slightly fixed the problem- so instead of
$scope.updateSubject = function () {
SubjectFactory.update($scope.subject);
$location.path('/subjects/');
$scope.subjects = SubjectsFactory.query();
$route.reload();
};
It is now
$scope.updateSubject = function () {
SubjectFactory.update($scope.subject).$promise.then(function (subject) {
$scope.subject = subject;
$location.path('/subjects/');
$route.reload();
}, function (err) {
console.error(err);
});
};