I spent several hours on this problem and I can not figure this out :( I know that I tested that functionality about a week or so ago and I saw 2 toastr error messages displayed (I didn't want two of them, though). I am not sure what exactly changed but now I can not get even a single one displayed :( I see no toastr message at all.
My code is:
app.directive('serverError', ['resourceFactory', 'spinnerService', 'toastr', '$log',
function (resourceFactory, spinnerService, toastr, $log) {
return {
restrict: 'A',
controller: ['$scope', '$timeout', function ($scope, $timeout) {
log = $log.getInstance("serverError");
var errorToastConfig = {
closeButton: true,
timeOut: 0,
extendedTimeOut: 0,
tapToDismiss: false,
preventDuplicates: true
};
var title = resourceFactory.getResource("Messages", "applicationError");
$scope.$on('sm:badRequest', function (event, data) {
if (!$scope.errorHandled && !$scope.showForm) {
log.debug("Handling bad request");
let errorMsg = "";
angular.forEach(data, function (value, key) {
if (value.message == '') value.message = 'The ' + value.property + ' value is invalid.'
errorMsg = errorMsg + value.message + " ";
});
errorMsg = errorMsg.trim();
$scope.errors = data;
toastr.clear();
if (errorMsg=="")
errorMsg = resourceFactory.getResource('Messages', 'errorOnForm');
title = resourceFactory.getResource("Messages", "badRequest");
toastr.error(errorMsg, title, errorToastConfig);
}
$scope.disableAction = false;
});
And then also in the controller:
function (error) {
spinnerService.stopSpinner('loaditemtree');
$scope.stopExecution = true;
if (error.hasOwnProperty("data")) {
toastr.clear();
let errorMsg = error.data[0].message;
toastr.error(errorMsg);
}
});
I see in the console [ItImagesSearchController] Init of the Images Search Controller is firing...
/SiriuswareControl/api/itDraftHeaders/1019 Failed to load resource: the server responded with a status of 400 (Bad Request)
2angular.js:14525 [serverError] Handling bad request
I also trace my code in the controller and I can see the line with toastr being executed. However, I see no toastr :( What can possibly be wrong?
I believe I figured this out, but I am sort of back to square 1. I wanted to prevent duplicate toastr messages from being displayed, thus I have preventDuplicates: true in the server error toastr config. However, it somehow made none of the messages to be displayed. When I slightly changed message in my controller, I saw both toastr messages now. How can I make only one of them to show?
Related
When I load the page for first time, I'm getting 200 status code and the page is loading file. The problem is from second time getting 304 status and the page is not working. How to set the cache control off for the particular JSON file in my JS file
var app = angular.module("myApp", ['angular.filter']);
app.controller("deviceCtrl", function($scope, $rootScope, $http,$timeout) {
var planReq = $http.get("data/callplans.json").then(function (response1) {
$scope.callplanList = response1.data;
return response1;
});
});
try this..:
var planReq = $http.get("data/callplans.json?r=" + Math.random() ).then(function (response1) {
I am trying to submit a form with ng-file-upload that contains additional form data. I had it working fine when the file was required, but now the client wants the file upload to be optional. I modified the PHP service to accept the new data, and it works fine.
The issue is displaying a success message when there is no file attached to the form. The data is received and processed fine by the service, but now I can't get it to indicate that the submission was successful.
I really don't want to have to shift gears at this point, and I like ng-file-upload's preview feature. I tried changing the checked variable in the ng-show directive for the success message and setting it in the .then function, but that doesn't work.
The only thing I can think of is to branch the code based on whether the file input is present and send it via regular $http if it isn't, but is there a better way?
Here's my controller code:
app.controller('adController', ['$scope', 'Upload', '$timeout', function ($scope, Upload, $timeout) {
//$scope.text = "Is this working?";
$scope.ad = {};
$scope.isSaving = false; // disables fieldset to prevent accidental double-click submissions
$scope.successful_post = false;
$scope.errorClass = function(el) {
var s = $scope.adApplicationForm[el];
return (s.$invalid && s.$dirty) ? "has-error" : "";
};
$scope.submitForm = function(valid) {
console.log("Form Submitted" + valid)
return valid;
};
$scope.uploadPic = function(file) {
$scope.isSaving = true;
file.upload = Upload.upload({
url: 'php/upload_ad.php',
data: {ad: $scope.ad, file: file},
});
file.upload.then(function (response) { // success
$timeout(function () {
file.result = response.data;
});
$scope.isSaving = false;
$scope.successful_post = true;
}, function (response) {
if (response.status > 0)
$scope.errorMsg = response.status + ': ' + response.data;
}, function (evt) {
// Math.min is to fix IE which reports 200% sometimes
file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
});
};
}]);
Thanks for your help.
I am working on a card processing API with ASP.NET , HTML , AngularJS and Stripe.NET. I am pretty new to all of them.
I followed the documentation on the Stripe website for sending the Stripe token to the server (here): https://stripe.com/docs/stripe.js#card-validateCardNumber
It worked! However, instead of JQuery I want to use AngularJS. I want to convert from JQuery to AngularJS this part of the JQuery code:
Stripe.card.createToken({
number: $('.card-number').val(),
cvc: $('.card-cvc').val(),
exp_month: $('.card-expiry-month').val(),
exp_year: $('.card-expiry-year').val(),
address_zip: $('.address_zip').val()
}, stripeResponseHandler);
function stripeResponseHandler(status, response) {
// Grab the form:
var $form = $('#payment-form');
if (response.error) { // Problem!
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false); // Re-enable submission
} else { // Token was created!
// Get the token ID:
var token = response.id;
// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// Submit the form:
$form.get(0).submit();
}
}
If someone can help, I will appreciate it a lot. Thanks. :)
I was able to answer my question (a while ago, just finding some time to answer it in here).
Firstly, here are the tips:
Use "angular-payments.js". You can find it here: https://github.com/laurihy/angular-payments
You have to use the html syntax for the card details as in the documentation of the repository.
It is not the same as in the Stripe documentation. I have used AngularJS service so that I can pass my token to my ASP.NET application.
Thirdly, I had problems with the verification token - here is a nice post for how to handle it: http://blog.novanet.no/anti-forgery-tokens-using-mvc-web-api-and-angularjs/
Here is (part of) my (AngularJS) code:
(function () {
var app = angular.module("myApp", ["angularPayments"]);
app.service('Service', function ($http) {
this.AddCard = function (stripeToken, stripeEmail) {
var tokenData = {
"stripeToken": stripeToken,
"stripeEmail": stripeEmail
};
$http.post("http://localhost:48484/payment/card", tokenData).success(function (response) {
window.location = '/cardprocess/confirmation';
})
};
});
app.directive('ncgRequestVerificationToken', ['$http', function ($http) {
return function (scope, element, attrs) {
$http.defaults.headers.common['RequestVerificationToken'] = attrs.ncgRequestVerificationToken || "no request verification token";
};
}]);
app.controller("myCtrl", ['$scope', myCtrl]);
app.controller("buyCtrl", function ($scope, CardService) {
$scope.submit = function () {
$scope.processing = true;
}
$scope.stripeFormSubmit = function (code, result) {
$scope.processing = false;
$scope.hideAlerts();
if (result.error) {
$scope.stripeError = result.error.message;
} else {
//$scope.stripeToken = result.id;
$scope.stripeToken = result.id;
CardService.AddCard($scope.stripeToken, $scope.stripeEmail);
}
};
$scope.hideAlerts = function () {
$scope.stripeError = null;
$scope.stripeToken = null;
};
});
}());
(The html page is quite big so I decided not to put in here. It should be straight forward - I have a form, which calls AngularJS model "stripeFormSubmit".)
Finally, you can see the "CardService", which is talking to my api - the service is initialised at the begining of the paste code.
That is the main idea. I decided not to go in a lot of detail. But I will try to answer questions (if any).
Im trying to verify that a user is logged in. Initially I went with $scope.use, $scope.user.uid, $scope.getCurrenUser() as described on Firebase docs but I think I simply have the dependencies wrong.
Code:
myApp.js
https://gist.github.com/sebbe605/2b9ff7d3b798a58a3886
firebase.js
https://gist.github.com/sebbe605/f9e7b9a75590b3938524
If I understand this correctly there is no way for the program to know that I'm referring to a Firebase user. To clarify I want .controller('templateCtrl',function($scope, $firebase) to have the ability to show a certain button if the user is logged in.
--UPDATE 1--
So, i have updated my files and for what i understand this should work. Previous code are as gits above to enhance the cluther.
myApp.js
angular.module('myApp', [
'ngRoute',
'firebase'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/template',
{
templateUrl:'partials/template.html', controller:'templateCtrl'
});
$routeProvider
.when('/login',
{
templateUrl:'partials/login.html', controller:'signupCtrl'
});
$routeProvider
.when('/signup',
{
templateUrl:'partials/signup.html', controller:'signupCtrl'
});
$routeProvider
.when('/user',
{
templateUrl:'partials/user.html', controller:'userCtrl'
});
$routeProvider
.otherwise('/template');
}])
controllers.js
'use strict';
angular.module('myApp').controller('signupCtrl', function($scope, $http, angularFire, angularFireAuth){
$scope.loginBusy = false;
$scope.userData = $scope.userData || {};
var ref = new Firebase('https://boostme.firebaseio.com/');
angularFireAuth.initialize(ref, {scope: $scope, name: 'user'});
/*//////////////LOGIN - LOGOUT - REGISTER////////////////////*/
$scope.loginEmailText = "Email"
$scope.loginPasswordText = "Password"
$scope.login = function() {
$scope.loginMessage = "";
if ((angular.isDefined($scope.loginEmail) && $scope.loginEmail != "") && (angular.isDefined($scope.loginPassword) && $scope.loginPassword != "")) {
$scope.loginBusy = true;
angularFireAuth.login('password', {
email: $scope.loginEmail,
password: $scope.loginPassword
});
} else {
$scope.loginPassword = ""
$scope.loginPasswordText = "Incorrect email or password"
}
};
$scope.logout = function() {
$scope.loginBusy = true;
$scope.loginMessage = "";
$scope.greeting = "";
$scope.disassociateUserData();
$scope.userData = {};
angularFireAuth.logout();
};
$scope.emailText = "Email"
$scope.passwordText = "Password"
$scope.confirmPasswordText = "Confirm Password"
$scope.register = function() {
$scope.loginMessage = "";
if ((angular.isDefined($scope.email) && $scope.email != "") && (angular.isDefined($scope.password0) && $scope.password0 != "" && $scope.password0 == $scope.password1)) {
$scope.loginBusy = true;
angularFireAuth.createUser($scope.email, $scope.password0, function(err, user) {
if (user) {
console.log('New User Registered');
}
$scope.loginBusy = false;
});
} else {
$scope.password0 =""
$scope.password1 =""
$scope.passwordText = "Password Not Matching"
$scope.confirmPasswordText = "Password Not Matching"
}
};
$scope.$on('angularFireAuth:login', function(evt, user) {
$scope.loginBusy = false;
$scope.user = user;
console.log("User is Logged In");
angularFire(ref.child('users/' + $scope.user.id), $scope, 'userData').then(function(disassociate) {
$scope.userData.name = $scope.userData.name || {};
if (!$scope.userData.name.first) {
$scope.greeting = "Hello!";
} else {
$scope.greeting = "Hello, " + $scope.userData.name.first + "!";
}
$scope.disassociateUserData = function() {
disassociate();
};
});
});
$scope.$on('angularFireAuth:logout', function(evt) {
$scope.loginBusy = false;
$scope.user = {};
console.log('User is Logged Out');
});
$scope.$on('angularFireAuth:error', function(evt, err) {
$scope.greeting = "";
$scope.loginBusy = false;
$scope.loginMessage = "";
console.log('Error: ' + err.code);
switch(err.code) {
case 'EMAIL_TAKEN':
$scope.loginMessage = "That email address is already registered!";
break;
case 'INVALID_PASSWORD':
$scope.loginMessage = "Invalid username + password";
}
});
})
Output:
Error: [$injector:unpr] Unknown provider: angularFireProvider <- angularFire
http://errors.angularjs.org/1.3.0-rc.3/$injector/unpr?p0=angularFireProvider%20%3C-%20angularFire
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:80:12
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:3938:19
at Object.getService [as get] (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4071:39)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:3943:45
at getService (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4071:39)
at invoke (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4103:13)
at Object.instantiate (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:4123:23)
at http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:7771:28
at link (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular-route.js:938:26)
at invokeLinkFn (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.3/angular.js:7549:9) <div ng-view="" class="ng-scope">
(anonymous function) angular.js:10683
(anonymous function) angular.js:7858
invokeLinkFn angular.js:7551
nodeLinkFn angular.js:7069
compositeLinkFn angular.js:6441
publicLinkFn angular.js:6320
boundTranscludeFn angular.js:6461
controllersBoundTransclude angular.js:7096
update angular-route.js:896
Scope.$broadcast angular.js:13751
(anonymous function) angular-route.js:579
processQueue angular.js:12234
(anonymous function) angular.js:12250
Scope.$eval angular.js:13436
Scope.$digest angular.js:13248
Scope.$apply angular.js:13540
done angular.js:8884
completeRequest angular.js:9099
xhr.onreadystatechange angular.js:9038
I cant figure out what the problem is. However i think there is something wrong with: but i can't tell. If more information is needed i'm happy to post it.
I initially was taking the same if-then-else approach as you do for handling privileged actions. But it turns out this is not the best approach when using Angular. Instead of having this if-then-else approach, try to reframe the problem to a solution that isolates the privileged code.
show a certain button if the user is logged in
So your original question was about showing an HTML element only when the user if logged in, which is easy with something like this in your controller:
$scope.auth = $firebaseSimpleLogin(new Firebase(FBURL));
This line binds the Firebase login status to the current scope, which makes it available to the view. No if-then-else is needed, since there is always a login status. AngularFire ensure that the view gets notified when that status changes, so all we have to do is ensure that we have the HTML markup to handle both presence and absence of authenticated users:
<div ng-controller="TrenchesCtrl" class='auth'>
<div ng-show="auth.user">
<p>You are logged in as <i class='fa fa-{{auth.user.provider}}'></i> {{auth.user.displayName}}</p>
<button ng-click="auth.$logout()">Logout</button>
</div>
<div ng-hide="auth.user">
<p>Welcome, please log in.</p>
<button ng-click="auth.$login('twitter')">Login with <i class='fa fa-twitter'> Twitter</i></button>
<button ng-click="auth.$login('github')">Login with <i class='fa fa-github'> GitHub</i></button>
</div>
</div>
See how it almost reads like an if-then-else? But then one without me writing code that tries to detect if the user is logged in. It is all declaratively handled by AngularJS and AngularFire.
perform actions only when a user is logged in
When you actually need to perform a privileged action, I've found it easiest to isolate the code like this:
function updateCard(id, update) {
var auth = $firebaseSimpleLogin(new Firebase(FBURL));
auth.$getCurrentUser().then(function(user) {
update.owned_by = user.username;
var sync = $firebase(ref.child('cards').child(id));
sync.$update(update);
});
};
Note that these are (simplified) fragments from my Trenches app (demo), which I wrote to learn more about Angular and AngularFire.
I have two views right now.
login
main
Right now I login and change my path to /main which works fine. When I am not logged in, and try to visit /main my web service returns "Access denied for user anonymous" which I then forward them to / which is my login view. How can I pass something so my LoginController knows they were forwarded from /main to alert them to login first?
LoginController.js
VforumJS.controller('LoginController', function($scope, $location, $routeParams, LoginModel)
{
$scope.email = "";
$scope.password = "";
$scope.fetching = false;
$scope.error = null;
$scope.login = function()
{
$scope.error = null;
$scope.fetching = true;
LoginModel.login($scope.email, $scope.password);
}
$scope.$on('LoginComplete', function(event, args)
{
log('login complete: ' + args.result);
$scope.fetching = false;
if (args.result == "success")
{
$location.path('/main');
}
else
{
$scope.error = args.result;
}
});
});
MainController.js
VforumJS.controller('MainController', function($scope, $location, $routeParams, MainModel)
{
$scope.currentTitle = '-1';
$scope.presentationData = MainModel.getPresentations();
$scope.$on('PresentationsLoaded', function(event, args)
{
log(args.result);
if (args.result != "Access denied for user anonymous")
{
//-- Parse preso data
$scope.presentationData = args.result;
}
else
{
//-- Need to login first, route them back to login screen
$location.path("/");
}
});
});
You can use $location.search() in your MainController to pass query string to the LoginController.
Inside you MainController:
if (args.result != "Access denied for user anonymous")
{
//-- Parse preso data
$scope.presentationData = args.result;
}
else
{
//-- Need to login first, route them back to login screen
$location.search({ redirectFrom: $location.path() });
$location.path("/");
}
And then in your LoginController, shortened for brevity:
VforumJS.controller('LoginController', function($scope, $location, $routeParams, LoginModel)
{
var queryString = $location.search();
$scope.$on('LoginComplete', function(event, args)
{
log('login complete: ' + args.result);
$scope.fetching = false;
if (args.result == "success")
{
if (queryString && queryString.redirectFrom) {
$location.path(queryString.redirectFrom);
} else {
$location.path('/somedefaultlocation');
}
}
else
{
$scope.error = args.result;
}
});
});
Alternatively you can use a shared service, maybe even your LoginModel to set a parameter from MainController to indicate the redirect came from it.
Update
Even better still, use $httpProvider.interceptors to register a response interceptor, and then use the same $location.search() technique described above to redirect to the login screen on authentication failure. This method is ideal as your controllers are then clean of authentication logic.
$location broadcasts $locationChangeStart and $locationChangeSuccess events, and the third param of each is oldUrl.
One solution would be to have a service that subscribes to $locationChangeStart in order to save the current and old urls.
When you hit /, your LoginController can check your service to see if the oldUrl is /main, and then act accordingly.