I have the following code. I am using ng-show on html and try to manipulate it on the angular function but it did not work. I am not sure about the correct way to change a $scope value inside a function.
On Angular,
app.controller("ControlController", function($scope, $http, $location) {
$scope.badRequest = false;
$scope.login = function() {
$http.post('/login', {
email: $scope.email,
password: $scope.password
}).then function(res) {
$location.path('/');
},function(err) {
$scope.badRequest = true;
console.log($scope.badRequest); // this will print true.
//But this does not change the $scope.badRequest on DOM.
});
};
});
On Jade, I have
.incorrect-container(ng-show='badRequest')
Any help?
Not sure if it's just that you copied it over wrong, but ".then" is a function call. it should be
$scope.login = function() {
$http.post('/login', {
email: $scope.email,
password: $scope.password
})
.then(function(data) {
// do stuff in here with successfully returned data
})
.catch(function(err) {
$scope.badRequest = true;
});
};
The way you have it, .then is not even being called. Also, when I ran it as it was, I got syntax errors. are you not getting those?
Related
I have two mongoose schemas running in on my server end. I would like to add two $http.get request in my app.js and eventually display two tables from my collection in MongoDB on a webpage. Only one get function is called without errors.
server.js
//Data Schema
var tempSchema = new mongoose.Schema({
topic: String,
message: Number,
when: Date
}, {collection: "temperature"});
var humiditySchema = new mongoose.Schema({
topic: String,
message: Number,
when: Date
}, {collection: "humidity"});
var temperature =mongoose.model('temperature', tempSchema);
var humidity =mongoose.model('humidity', humiditySchema);
app.js
app.controller("FormController", function ($http, $scope){
$http.get("/api/temperature")
.then(function (response) {
$scope.temperatures = response.data;
});
})
app.controller("FormController", function ($http, $scope){
$http.get("/api/humidity")
.then(function (response) {
$scope.humiditys = response.data;
});
})
Also thinking of how I can display both collections on the webpage. Using ng-repeat. Unfortunately I cannot paste my HTML code here.
I would appreciate any help I can get. Thanks
Another way you could handle the $http requests is by creating an Angular Factory.
angular.module('myApp.services',[])
add.factory('ApiService', function($http) {
return {
getHumidity: function() {
return $http.get("/api/humidity");
},
getTemperature: function() {
return $http.get("/api/temperature");
}
}
})
Then inside your controller, you should do the following (Note that you must inject the factory as a dependency for the controller)
angular.module('myApp.controllers',[])
.controller("FormController", function (ApiService, $scope){
function getHumidity() {
var promise = ApiService.getHumidity();
promise.then(
function(response) {
$scope.humiditys = response.data;
},
function(errorPayload) {
console.log(errorPayload);
});
};
function getTemperature() {
var promise = ApiService.getTemperature();
promise.then(
function(response) {
$scope.temperatures = response.data;
},
function(errorPayload) {
console.log(errorPayload);
});
};
getHumidity();
getTemperature();
})
then where you define your angular App (app.js in most of the cases):
angular.module('myApp', ['myApp.controllers','myApp.services'])
.run(...)
.config(...)
...
I'm developing a web application in java with NetBeans
using AngularJS.
When I'm accessing my WebService in localhost I'm getting the JSON array with the objects that I need, working very well
BUT
in the controller, I'm not getting the information
Log of the Web browser:
Result: [object Object] OR {} script.js:140:5
Success/Error: undefined
Code:
minhaAplicacao.controller('inicioPacienteCTRL', function ($scope, $http) {
$scope.medicoSelecionado;
var aux;
var $scope.result = window.console.log($http.get("http://localhost:8080/Clinica5/webresources/medicos")).then(function (success) {
aux = success;
}, function (error) {
aux = error;
});
window.console.log("Result: "+$scope.result+ " OR "+JSON.stringify($scope.result));
window.console.log("Success/Error: "+aux);
});
And if I put this code in the view I got an error:
<div ng-bind="$scope.result"></div>
Error: $scope.result is not defined
I have configured the $routeProvider and is absolutely correct
Thanks a lot <3 Big Hug!
You can try in the following way.
minhaAplicacao.controller('inicioPacienteCTRL', function ($scope, $http) {
$scope.functionName = function(){
//define
$scope.medicoSelecionado = {};
$http.get("http://localhost:8080/Clinica5/webresources/medicos").then(function (success) {
console.log(success);
//success data passed
$scope.medicoSelecionado = success;
}, function (error) {
console.log(error);
//error message
$scope.error = error;
});
}
});
And use this html to display error
<div class="error">{{error}}</div>
You need to assign your response to controller scope variable result as a result of asynch request like this
$scope.result = success
MoreOver you can avoid using var when declaring $scope variables
minhaAplicacao.controller('inicioPacienteCTRL', function ($scope, $http) {
$scope.medicoSelecionado;
$scope.aux = {};
$scope.result {};
$http.get("http://localhost:8080/Clinica5/webresources/medicos").then(function (success) {
$scope.result = success;
}, function (error) {
$scope.aux = error;
});
window.console.log("Result: ",$scope.result, " OR ",JSON.stringify($scope.result));
window.console.log("Success/Error:",$scope.aux);
});
also in view
<div ng-bind="result"></div>
no need of $scope
You have to define var aux = {} because if you not defined anything then it will show undefined
and you are getting object in success so that it is showing [object, object]
minhaAplicacao.controller('inicioPacienteCTRL', function ($scope, $http) {
$scope.medicoSelecionado;
var aux = {};
var $scope.result = window.console.log($http.get("http://localhost:8080/Clinica5/webresources/medicos")).then(function (success) {
aux = success;
}, function (error) {
aux = error;
});
window.console.log("Result: "+$scope.result+ " OR "+JSON.stringify($scope.result));
window.console.log("Success/Error: "+aux);
});
Try <div ng-model="result"></div> for the second error.
And no need to do:
$scope.medicoSelecionado;
$scope.aux;
$scope.result;
Just use a new model when you need one; no declaration is needed.
Doing $scope.result = successin your .then() should be fine, as suggested by Vinod Louis.
The way I would do it:
minhaAplicacao.controller('inicioPacienteCTRL', function ($scope, $http) {
$http.get("http://localhost:8080/Clinica5/webresources/medicos")
.then(function (success) {
$scope.result = success;
}, function (error) {
$scope.result = error;
});
window.console.log("Result: "+$scope.result+ " OR "+JSON.stringify($scope.result));
});
What does aux do by the way?
GOT!
For some reason was having conflict with the route 'login'. I don't known why.
The solution was deleting the redirectTo line
when('/inicioMedico', {
templateUrl: 'inicioMedico.html',
controller: "inicioMedicoCTRL"
}).
otherwise ({
// redirectTo: 'login' ERROR HERE
});
First project in AngularJS and I started creating my services (factories) that I made modular like this
angular.module('app.services.public', [])
.factory('publicService', ['$http', function publicService($http) {
var results = {};
results.contact = function (name, email, message){
return $http.get();
};
return results;
}]);
That I then call in my main angular app by including it. When I call it, I need to listen for success or error
publicService.contact().success(callback).error(callback)
My question is, I'm going to be doing a lot of API requests through these services and seems to be bad code to listen to the error everytime since 90% of the time it will do the same thing.
How can I create a wrapper around the $http.get or around all factory calls?
So something like
apiCall = function (url, data, successCallback, errorCallback){
$http.get(url,data).success(function(){
successCallback()
}).error(function(){
if(errorCallback()){ errorCallback(); return; }
// or display general error message
})
}
I would recommend against converting promise-based into callback-based APIs. Angular adopted promises and it best to stay with them.
Also, stay away from $http-specific .success/.error and use promise .then/.catch APIs.
How wide do you need to cast your net to handle $http errors?
1) Say, it only applies to your publicService service, then you can "handle" it at the each function:
.factory("publicService", function($http, $q){
function handleError(){
// invokes error handlers
}
return {
onError: function(cb){
// register error handlers
},
doSomethingA: function(){
return $http.get("some/url/A")
.then(function(response){
return response.data;
})
.catch(function(error){
handleError(error);
return $q.reject(error); // still "rethrow" the error
}
},
doSomethingB: function(){
// similar to above
},
// etc...
};
})
Then you could separate request from error handling:
.controller("MainCtrl", function($scope, publicService){
publicService.onError(function(error){
$scope.showError = true; // or something like that
})
})
.controller("FunctionACtrl", function($scope, publicService){
publicService.doSomethingA()
.then(function(data){
$scope.data = data;
});
})
2) Of course, the above, would only apply to request made via publicService. If you want to catch all $http errors, you could implement an $http interceptors. I won't go into detail - there is enough info in documentation and elsewhere - but it would could work like below:
.factory("ErrorService", function(){
return {
onError: function(cb){
// register error handlers
},
broadcastError: function(error){
// invoke error handlers
}
};
})
Then in interceptor, use ErrorService as a dependency:
'responseError': function(rejection) {
ErrorService.broadcastError(rejection);
return $q.reject(rejection);
}
Then you could handle the errors globally:
.controller("MainCtrl", function($scope, ErrorService){
ErrorService.onError(function(error){
$scope.showError = true; // or something like that
})
})
You have the right idea. You can do it easily with a Factory.
myApp.factory(APIService, function(publicService, $http) {
return {
// create methods in here
...
contact: function(cb) {
$http.get(url,data).success(cb).error(function(err){
console.error('oh no!', err);
});
}
};
});
Then you can use it in your controllers.
APIService.contact(function(data){
console.log('response from the api!', data);
});
You can even move your error handler to its own factory as well.
I would suggest an implementation using angular's $q service.
angular.module('app.services.public', [])
.factory('publicService', ['$http', '$q', function publicService($http, $q) {
var results = {};
results.contact = function (name, email, message){
return $q.when($http.get());
};
return results;
}]);
Or rather than use the $q.when(...) method you can use $q.deferred like so:
angular.module('app.services.public', [])
.factory('publicService', ['$http', '$q', function publicService($http, $q) {
var deferred = $q.deferred();
var results = {};
results.contact = function (name, email, message){
$http.get().success(function(data){
deferred.resolve({
// assumes data retried from http request has a title and price attribute
title: data.title,
cost: data.price});
}).error(function(data){
deferred.reject(data);
});
};
return deferred.promise;
}]);
I am using Angular (1.3.5) and Firebase to write a toy blog program, and am currently struggling with the user login part.
I first created an Angular module:
var blogApp = angular.module('blogApp', ['ngRoute', 'firebase', 'RegistrationController']);
Then on top of blogApp, I created a controller called ** RegistrationController **:
blogApp.controller('RegistrationController', function ($scope, $firebaseAuth, $location) {
var ref = new Firebase('https://myAppName.firebaseio.com');
// var authLogin = $firebaseAuth(ref);
$scope.login = function(){
ref.authWithPassword({
email: $scope.user.email,
password: $scope.user.password
}, function(err, authData) {
if (err) {
$scope.message = 'login error';
} else {
$scope.message = 'login sucessful!';
}
});
}; // login
}); //RegistrationController
I attached the login() method to ng-submit in my user-login form in the scope of RegistratinController.
When I click to submit the login form, the form does not make any response, without any errors showing.
The login form works only when I click the 'Submit' button twice - why is this? confusing
You are using the Firebase JavaScript library and not AngularFire for the login methods.
You need to pass the Firebase reference into the $firebaseAuth binding.
var auth = $firebaseAuth(ref);
From there you can call auth.$authWithPassword.
$scope.login = function(){
auth.$authWithPassword({
email: $scope.user.email,
password: $scope.user.password
}, function(err, authData) {
if (err) {
$scope.message = 'login error';
} else {
$scope.message = 'login successful!';
}
});
}; // login
AngularFire is an Angular binding for the Firebase Library that handles auto syncing over objects and arrays. AngularFire also handles when to call $scope.apply to properly update the view.
In your case, the login code is working the first click, but it doesn't get applied to the page. You can wrap this code in a $timeout, but it would be better to use the $firebaseAuth service.
Thanks to user jacobawenger, for the solution he posted here:
Can't get new password authentication methods to work in AngularFire 0.9.0?
This works as expected:
myApp.controller('RegistrationController',
function($scope, $firebaseAuth, $location) {
var ref = new Firebase('https://myApp.firebaseio.com');
var simpleLogin = $firebaseAuth(ref);
$scope.login = function() {
simpleLogin.$authWithPassword({
email: $scope.user.email,
password: $scope.user.password
}).then(function() {
$location.path('/mypage');
}, function(err) {
$scope.message = err.toString();
});
} // login
}); // RegistrationController
Here's my code in the service.
this.loginUser = function(checkUser) {
Parse.User.logIn(checkUser.username, checkUser.password, {
success: function(user) {
$rootScope.$apply(function (){
$rootScope.currentUser = user;
});
}
});
};
Here's my code in the controller:
$scope.logIn = function(){
authenticationService.loginUser($scope.checkUser);
console.log($scope.currentUser)
};
So, what I want to do is, execute some code AFTER the completion of AJAX call, whose success function sets the value of $scope.currentUser, which, I can use for some conditional logic (like redirecting etc)
The success function is correctly setting the value, but the console.log should be executed AFTER the execution of authenticationService.loginUser() function.
You need to return a promise using $q and act on that.
For instance in your service:
this.loginUser = function(checkUser) {
var deferred = $q.defer();
Parse.User.logIn(checkUser.username, checkUser.password, {
success: function(user) {
$rootScope.$apply(function (){
$rootScope.currentUser = user;
});
deferred.resolve();
}
});
return deferred.promise;
};
Then in your controller act on the success:
$scope.logIn = function(){
authenticationService.loginUser($scope.checkUser).then(function() {
console.log($rootScope.currentUser));
});
};
Try using $rootScope.$broadcast in your service then listen for it in your controller:
Service
Parse.User.logIn(checkUser.username, checkUser.password, {
success: function(user) {
$rootScope.$apply(function (){
$rootScope.currentUser = user;
$rootScope.$broadcast('user.online');
});
}
});
Controller
$scope.$on('user.online',function(){
[ DO STUFF HERE ]
});
This isn't the best way to do this though #comradburk's use of $q is probably a better way.
If your application wait for external result, you should use $q for return a promise. If you are using angular-route or ui-router components, you can use resolve param for this. Take a look ngRoute documentation. In there has a example based in resolve param.
https://docs.angularjs.org/api/ngRoute/service/$route
i think you have two options here
as answered by comradburk, use promises:
in Services:
this.loginUser = function(checkUser) {
var deferred = $q.defer();
Parse.User.logIn(checkUser.username, checkUser.password, {
success: function(user) {
deferred.resolve(user);
}
});
return deferred.promise;
};
in controller:
$scope.logIn = function(){
authenticationService.loginUser($scope.checkUser).then(function(user) {
$scope.currentUser = user;
});
};
using resolve, resolve your service at route level (...or state level in case you are using ui-router) before controller initialization and insert it as a dependency - helpful in scenarios like user authentication where you dont want user to be able to navigate further if authentication fails. from docs
https://docs.angularjs.org/api/ngRoute/service/$route
YOMS (Yet One More Solution):
this.loginUser = function(checkUser, onSuccess) {
Parse.User.logIn(checkUser.username, checkUser.password, {
success: function(user) {
$rootScope.$apply(function() {
$rootScope.currentUser = user;
if (typeof onSuccess == 'function') onSuccess(user); // optionally pass data back
});
}
});
};
$scope.logIn = function(user, function(returnedUser) {
// console.log(returnedUser); // Optional, The returned user
console.log($scope.currentUser)
}) {
authenticationService.loginUser($scope.checkUser);
};