ng-model from angular-payments is not working - angularjs

I am trying to add angular-payments in order to integrate stripe.com payment processing to my AngularJS web app.
I duplicated the code from https://github.com/laurihy/angular-payments/blob/master/lib/angular-payments.js into my angular-payments.js file and the code from https://github.com/laurihy/angular-payments/blob/master/example/index.html into localhost:8888/stripe.html and got it to work.
However, when I try to integrate this code to my AngularJS web app, the ng-model is not working.
Here is how I integrated the code. I have a single page web app with app.js, which has the following code:
angular.module('io.config', []).value('io.config', {
'password': 'json/config.password.json',
....
....
});
...
...
angular.module('app.modules', ['app.config']);
var app = angular.module('app', ['ngCookies', 'io', 'ui', 'bs', '$strap',
'app.controllers', 'app.directives', 'app.factories', 'app.filters', 'app.modules', 'app.config']);
So, I added 'angularPayments' to:
var app = angular.module('app', ['ngCookies', 'io', 'ui', 'bs', '$strap',
'app.controllers', 'app.directives', 'app.factories', 'app.filters', 'app.modules', 'app.config', 'angularPayments']);
I also have an app.route.js file, which has the following code:
angular.module('app')
.config(['$routeProvider', function($routeProvider) {
var _view_ = 'view/', _app_ = 'app/';
$routeProvider
.when('/user/invite', {templateUrl:_view_+'app/invite.html'})
I added the following to app.route.js:
.when('/user/buy', {templateUrl:_view_+'app/buy.html'})
I duplicated the code from localhost:8888/stripe.html into app/buy.html, which maps to localhost:8888/#/user/buy
The exception is that I took the following lines out of buy.html and put them into index.html:
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script src="scripts/modules/angular-payments.js"></script>
My index.html has this code:
<!DOCTYPE html>
<html class="no-js" lang="en" data-ng-app="app">
...
<link href="./css/bootstrap.css" rel="stylesheet">
...
<body class="ng-cloak" data-ng-controller="AppCtrl">
...
<div data-ng-view></div>
...
<script src="bower_components/angular-io/src/scripts/ie.js"></script>
...
<script src="bower_components/angular-complete/angular.js"></script>
...
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script src="scripts/modules/angular-payments.js"></script>
...
Both stripe.html and buy.html has the following code:
<form stripe-form="handleStripe">
<div class="span3">
<label for="">Card number</label>
<input type="text" class="input-block-level" ng-model="number" payments-validate="card" payments-format="card" />
</div>
<div class="span1">
<label for="">Expiry</label>
<input type="text" class="input-block-level" ng-model="expiry" payments-validate="expiry" payments-format="expiry" />
</div>
<div class="span3">
<label for="">Name on card </label>
<input type="text" class="input-block-level">
</div>
<div class="span1">
<label for="">CVC</label>
<input type="text" class="input-block-level" ng-model="cvc" payments-validate="cvc" payments-format="cvc" />
</div>
<div class="span4">
<button type="submit" class="btn btn-primary btn-large">Submit</button>
</div>
number:{{number}}, expiry:{{expiry}}, cvc:{{cvc}}
</form>
However, the following code works in stripe.html but not in buy.html, as no values are coming back from the ng-model:
number:{{number}}, expiry:{{expiry}}, cvc:{{cvc}}
Hence, when I submit this form, Stripe returns an error with status = 402 because nothing is passed to Stripe.
I've tried changing ng-model to data-ng-model, but to no avail. I've tried putting the following code into a separate file: scripts/controllers/payment.js:
function PaymentCtrl($scope) {
$scope.handleStripe = function(status, response){
if(response.error) {
// there was an error. Fix it.
} else {
// got stripe token, now charge it or smt
token = response.id
}
}
}
and adding the following to app.route.js:
.when('/user/buy', {templateUrl:_view_+'app/buy.html', controller:PaymentCtrl})
and changing the following in buy.html:
data-ng-controller="MainController"
to:
data-ng-controller="PaymentCtrl"
but still to no avail.
Can anyone tell me how to get the ng-model variables to work in buy.html? Thanks in advance.

I got a tip from Ng-model does not update controller value and I solved the problem with a convoluted solution.
I added the following code to MainController in buy.html:
$scope.payment = {};
$scope.copyvariables = function() {
$scope.number = $scope.payment.number;
$scope.expiry = $scope.payment.expiry;
$scope.cvc = $scope.payment.cvc;
}
Then I added "payment." to the ng-model variables, like such:
<div class="span7">
<label for="">Card number</label>
<input id="number" name="number" type="text" class="input-block-level" data-ng-model="payment.number" payments-validate="card" payments-format="card" required />
</div>
<div class="span4" style="border: 1px solid red">
<label for="">Expiry</label>
<input type="text" class="input-block-level" data-ng-model="payment.expiry" payments-validate="expiry" payments-format="expiry" required />
</div>
<div class="span8">
<label for="">Name on card </label>
<input id="name" name="name" type="text" class="input-block-level" required />
</div>
<div class="span3">
<label for="">CVC</label>
<input type="text" class="input-block-level" data-ng-model="payment.cvc" payments-validate="cvc" payments-format="cvc" required />
</div>
Now the following code works and the values are being passed to Stripe:
number:{{number}}, expiry:{{expiry}}, cvc:{{cvc}}
I still don't know why I need this for buy.html but stripe.html works without this extra code.

Related

How to store values from a form to local storage in AngularJS?

I have some code for adding the values from a form to the local storage,
but when I tried the code, it is not running. I would like to store the form data in local storage by clicking the button. I am adding my sample code below:
App.controller('KeyController', function($scope,$localStorage) {
/*$scope.info = 'Welcome to Test';*/
/*console.log(" Key controller is working ");*/
$scope.api_url;
$scope.api_token;
$scope.submit=function(){
localStorage.setItem('api_url','--------');
localStorage.setItem('api_token','--------');
console.log(api_url);
console.log(api_token)
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container">
<form role = "form" id="uriForm" name="authfrom">
<div class = "form-group">
<label for = "url">Enter the url to authenticate:</label>
<input type = "url" class = "form-control" placeholder = "Enter the URL" ng-model="api_url" required="required">
</div>
<div class = "form-group">
<label for = "Key">Enter the key here:</label>
<textarea class = "form-control" rows="5" placeholder = "Enter the Key" ng-model="api_token" required="required"></textarea>
</div>
<button class = "btn btn-default" ng-click="submit()">Explore!!</button>
<p class="warning">{{failed}}</p>
</form>
</div>
You haven't add your app.js file in html.
You didn't add your ng-app and ng-controller in html.
You were adding $localStorage in function which is not necessary.
You were using wrong syntax for localStorage.setItem()
Now I've edited your code and made this.
Here is index.html page
<!DOCTYPE html>
<html ng-app="app">
<head>
<title>App</title>
<script src="angular/angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-controller="KeyController">
<div class="container">
<form>
<div class = "form-group">
<label for = "url">Enter the url to authenticate:</label>
<input type = "text" class = "form-control" placeholder = "Enter the URL" ng-model="api_url" required="required">
</div>
<div class = "form-group">
<label for = "Key">Enter the key here:</label>
<textarea class = "form-control" rows="5" placeholder = "Enter the Key" ng-model="api_token" required="required"></textarea>
</div>
<button class = "btn btn-default" ng-click="submit()">Explore!!</button>
<p class="warning">{{failed}}</p>
</form>
</div>
</body>
</html>
Here is your app.js file:
angular.module('app', [])
.controller('KeyController', function($scope) {
$scope.api_url;
$scope.api_token;
$scope.submit=function(){
localStorage.setItem('api_url', JSON.stringify($scope.api_url));
localStorage.setItem('api_token', JSON.stringify($scope.api_token));
console.log($scope.api_url);
console.log($scope.api_token)
}
});
You can copy paste this and check your self. First replace the reference of angular.min.js file.
Please go through the below code which has been corrected to bootstrap the angular module and set controller using ng-app and ng-controller.
Code snippets posted on stackoverflow cannot access localstorage for the reason mentioned here. So you'll need to run this code on your local development environment.
angular
.module('MyApp', []);
angular
.module('MyApp')
.controller('KeyController', [
'$scope',
function($scope) {
/*$scope.info = 'Welcome to Test';*/
/*console.log(" Key controller is working ");*/
$scope.api_url;
$scope.api_token;
$scope.savedApiUrl = '';
$scope.savedApiToken = '';
$scope.submit = function() {
localStorage.setItem('api_url', $scope.api_url);
localStorage.setItem('api_token', $scope.api_token);
var savedApiUrl = localStorage.getItem('api_url');
var savedApiToken = localStorage.getItem('api_token');
$scope.savedApiUrl = savedApiUrl;
$scope.savedApiToken = savedApiToken;
console.log($scope.savedApiUrl);
console.log($scope.savedApiToken)
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-app="MyApp" ng-controller="KeyController">
<form role="form" id="uriForm" name="authfrom">
<div class="form-group">
<label for="url">Enter the url to authenticate:</label>
<input type="url" class="form-control" placeholder="Enter the URL" ng-model="api_url" required="required">
</div>
<div class="form-group">
<label for="Key">Enter the key here:</label>
<textarea class="form-control" rows="5" placeholder="Enter the Key" ng-model="api_token" required="required"></textarea>
</div>
<button class="btn btn-default" ng-click="submit()">Explore!!</button>
<p class="warning">{{failed}}</p>
</form>
<p>Saved values from local storage</p>
<p>API URL: {{savedApiUrl}}</p>
<p>API Token: {{savedApiToken}}</p>
</div>

NVDA ignores angular *ngIf blocks with role="alert"

My aim is to give the user information about errors in inputs. I am able to do that without angular with this example. I also managed to recreate the following example with using "innerHTML" attribute but it also didn't work with NVDA, in short it just appends a node to body when error occures
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<title>Contact form (WAI-ARIA)</title>
<script type="text/javascript">
function removeOldAlert()
{
var oldAlert = document.getElementById("alert");
if (oldAlert)
document.getElementById("error").removeChild(oldAlert);
}
function addAlert(aMsg)
{
removeOldAlert();
var newAlert = document.createElement("div");
newAlert.setAttribute("role", "alert");
newAlert.setAttribute("id", "alert");
var msg = document.createTextNode(aMsg);
newAlert.appendChild(msg);
document.getElementById("error").appendChild(newAlert);
}
function checkEntryValidity(aID, aSearchTerm, aMsg)
{
var elem = document.getElementById(aID);
var invalid = (elem.value.indexOf(aSearchTerm) < 0);
if (invalid) {
elem.setAttribute("aria-invalid", "true");
addAlert(aMsg);
} else {
elem.setAttribute("aria-invalid", "false");
removeOldAlert();
}
}
</script>
</head>
<body>
<form method="post" action="post.php">
<fieldset><legend>Please enter your contact details</legend>
<label for="name">Your name (required):</label>
<input name="name" id="name" aria-required="true" onblur="checkEntryValidity('name', ' ', 'Invalid name entered!');" aria-invalid="true" value=""><br>
<label for="email">E-Mail address (required):</label>
<input name="email" id="email" aria-required="true" onblur="checkEntryValidity('email', '#', 'Invalid e-mail address');" aria-invalid="true" value=""><br>
<label for="website">Website (optional):</label>
<input name="website" id="website" value="">
</fieldset>
<label for="message">Please enter your message (required):</label><br>
<textarea name="message" id="message" rows="5" cols="80" aria-required="true"></textarea><br>
<input name="submit" value="Send message" type="submit">
<input name="reset" value="Reset form" type="reset">
</form>
<div id="error"></div>
</body></html>
(alert Invalid name entered!)
but NVDA ignores this type of alert message
<!-- widget with model binding here -->
<div role="alert" class="validation" *ngIf="model.hasErrors()">
<div *ngFor="let message of model.errors">{{message}}</div>
</div>
I don't know why NVDA doesn't register that content change.
Angular2
I am using Windows 10, Firefox 50.1.0 and NVDA 2016.4.
It seems that adding aria-live like this
<div aria-live="assertive">
<div role="alert" class="validation" *ngIf="model.hasErrors()">
<div *ngFor="let message of model.errors">{{message}}</div>
</div>
</div>
allows the reader to register changes.

AngularJS v1.5.5 Reset form not working for invalid input fields

I have the code below (or see the fiddle) and I try to reset form and clear all input fields too for each form.
With AngularJS version 1.2.1 is working fine! but in my app I using version 1.5.5 because I have other libraries for separating the nested forms in <md-tab> tags using material framework who need this version.
The problem is when any field it's invalid then reset does not work as expected and these fields remain unchanged instead to be clear.
There is another way to clearing all fields (of nested form) when I click reset button ?
angular.module("main", [])
.controller("register", function($scope) {
$scope.data = {
A: {},
B: {}
};
$scope.reset = function(form) {
form.$setPristine();
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<body ng-app="main">
<div ng-controller="register" class="form">
<form name="form" novalidate role="form">
<div class="form">
<h1>TAB1 - Form A:</h1>
<ng-form name="A">
A1:
<input type="text" ng-model="data.A.A1" ng-minlength="4" ng-maxlength="15" />A2:
<input type="text" ng-model="data.A.A2" ng-minlength="4" ng-maxlength="15" />
<button type="button" ng-disabled="A.$pristine" ng-click="reset(A); data.A=null;">Reset</button>
<br/>
<strong>A.$pristine =</strong> {{A.$pristine}}
<strong>A.$valid =</strong> {{A.$valid}}
</ng-form>
</div>
<br/>
<br/>
<div class="form">
<h1>TAB2 - Form B:</h1>
<ng-form name="B">
B1:
<input type="text" ng-model="data.B.B1" ng-minlength="4" ng-maxlength="15" />B2
<input type="text" ng-model="data.B.B2" ng-minlength="4" ng-maxlength="15" />
<button type="button" ng-disabled="B.$pristine" ng-click="reset(B); data.B=null;">Reset</button>
<br/>
<strong>B.$pristine =</strong> {{B.$pristine}}
<strong>B.$valid =</strong> {{B.$valid}}
</ng-form>
</div>
</form>
<h1>data:</h1>
<pre>{{data | json}}</pre>
</div>
</body>
It's because ng-model binds to the A and B objects by reference in $scope.data. If you remove the $scope.data.A = null from your ng-click and reset the object without creating a new one, it works:
https://jsfiddle.net/utwf604r/15/
$scope.reset = function (form)
{
// don't change the reference to A
// $scope.data.A = {} wont work!!
angular.extend($scope.data, {A:{A1:'',A2:''}, B:{B1:'',B2:''}});
form.$setPristine();
};

Cannot find module with name 'my'. Cannot find controller with name 'mycontroller'

Hi I am getting the following error:
Error : Cannot find module with name "my".
And also
Multiple annotations found at this line:-
Cannot find module with name my. Cannot find module with name my.
Cannot find controller with name mycontroller
Please help. Thanks But I am able to run the code perfectly though the error exists.
My code is as below:
<!DOCTYPE html>
<html ng-app="my">
<head>
<script src="angular.js"></script>
<script>
var validation = angular.module('my', []);
validation.controller('mycontroller' , function($scope) {
$scope.firstName = "madhuri";
$scope.email = "madhuri#gmail.com";
$scope.age = "24";
$scope.pattern = /^\d*$/;
});
</script>
</head>
<body >
<div ng-controller="mycontroller">
<form name="form1">
<label>Name :</label> <input type="text" name="name" ng-model="firstName" required>
<span style="color: red" ng-show="form1.name.$error.required"> please provide the name</span>
<br>
<br>
<label>Email: </label> <input type="email"
name="email" ng-model="email">
<span style="color: red" ng-show="form1.email.$error.email"> please provide the valid email address </span>
<p style= "color: red" ng-show="form1.email.$error.email">please provide the valid email address</p>
<label>age :</label>
<input type="text" name="age" ng-model="age" ng-pattern="pattern">
<span style="color: red" ng-show="form1.age.$error.pattern"> please provide the correct age
</span>
</form>
</div>
</body>
</html> -->`
Try changing how your instantiating your controller. Try this:
<script>
var validation = angular.module('my', []);
angular.module('my').controller('mycontroller' , function($scope) {
$scope.firstName = "madhuri";
$scope.email = "madhuri#gmail.com";
$scope.age = "24";
$scope.pattern = /^\d*$/;
});
</script>
Alternatively you could also instantiate it like this:
<script>
var validation = angular.module('my', []).controller('mycontroller' , function($scope) {
$scope.firstName = "madhuri";
$scope.email = "madhuri#gmail.com";
$scope.age = "24";
$scope.pattern = /^\d*$/;
});
</script>
I have also added a JSFIDDLE that works both ways to show that they work
jsFiddle

angular removes ng-model variable if ng-required is true

as in the title.. how to prevent such operations to happen? Here is a link to the official site, see the example. The variable user.name is bound to the first input userName and if the input is empty the object user.name is removed. How can I disable this functionality of angularjs?
Try ng-model-options="{allowInvalid: true}" to update the model even for invalid entries.
<input ng-model="user.name" required ng-model-options="{allowInvalid: true}">
You've got 2 option
remove required from input tag it allows you to send back empty string to your backend
var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
$scope.params = {
user: "John"
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<input name="userName" ng-model="params.user" />
<hr/>
<pre>{{params| json}}</pre>
</div>
Option two validate your form before you send it to backend.
var app = angular.module('app', []);
app.controller('MyCtrl', function($scope) {
$scope.user = {
name: "John"
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<form name="someForm">
<input name="userName" ng-model="user.name" required name="userName" />
<span ng-show="someForm.userName.$error.required">User Name required</span>
<br/>{{user | json}}
<br/>
<button type="submit" ng-disabled="someForm.$invalid">Submit</button>
</form>
</div>

Resources