Hello I am running an app wich needs a lot of form validation across pages, so I am trying to get validation patterns from a service i am using amongst the controllers.
The problem here is the ng-pattern isn't reacting the right way when I enter a correct email address.
This is a plunker and here's the code for the form
<form method="POST" action="#" name="newsletterForm" id="newsletterForm" ng-controller="newsletterForm" novalidate>
<input ng-pattern="/{{patterns.email}}/" type="email" name="email" ng-model="email" required />
<button type="submit">Invia</button>
{{newsletterForm.email.$error.pattern}}
</form>
This is the app.js code
var app = angular.module('plunker', []);
app.controller('MainCtrl', function(){});
app.service('validationPatterns', function() {
this.getPatterns = function() {
return {
email: "^([a-zA-Z0-9\'\.\-\_]{2,64})([\#]{1})([a-zA-Z0-9\.\-\_]{2,64})([\.]{1})([a-zA-Z]{2,16})$"
}
}
});
app.controller('newsletterForm', function($scope, validationPatterns){
$scope.patterns = validationPatterns.getPatterns();
});
I assume the problem might be that when angular renders the pattern inside the input tag it renders it escaping the backslashes
^([a-zA-Z0-9'.-_]{2,64})([#]{1})([a-zA-Z0-9.-_]{2,64})([.]{1})([a-zA-Z]{2,16})$
I have already tried adding the double backslashes in the service to make angular render it correctly but it's still not working.
Any ideas?
ng-pattern works with a $scope variable. In your case it should be
<input ng-pattern="patterns.email"
Updated plunker
Related
I have a main JS file which holds a bunch of functions which are used throughout my app. In this JS file I set the routing of the app.
main.js (MainController):
$stateProvider
.state('page1', {
url : '/',
templateUrl : 'page1.html',
controller : "Page1Controller"
})
.state('page2', {
url : '/',
templateUrl : 'page2.html',
controller : "Page2Controller"
});`
In Page 2 I have a form
<div class="outer" ng-controller="MainController">
<div class="page" ng-init="test();">
<form id="page2_form" name="page2_form">
<input type="text" id="field1" name="field1"/>
<input type="text" id="field2" name="field2"/>
</form>
</div>
</div>
I will be using the scope to check the form for validation but currently it is undefined. I am checking this by using the $scope.$watch.
page2.js (Page2Controller):
$scope.$watch('page2_form', function(page2_form) {
console.log(page2_form);
});
But it is printing out "undefined". I assume that the routing is actually loading in the controller as the ng-init works. However, It does work if I try adding ng-controller="Page2Controller" to <div class="page"> this outputs the form on the $scope.$watch which is what I want but it is running it twice since the controller is being loaded twice.
Why is it not outputting the form even though the controller is being loaded in by the routing?
UPDATE
My fix:
Adding $scope.form = {}; to page2.js (Page2Controller) and changing the form to this:
<form id="form.page2_form" name="form.page2_form"></form>
This means that I can now access fields in the form with
$scope.form.page2_form[fieldname]
However, I'm not sure why I have to do this now as I have past applications where I did not need to do the form.form_name aspect of it.
I think your problem is related to JavaScript ProtoTypal inheritance and how Angular.js handling that in 'ng-*' directives.
Kindly check that link for more deep understanding to that topic.
https://github.com/angular/angular.js/wiki/Understanding-Scopes
Having these two files:
HTML:
<form name="registrationForm" ng-submit="registerUser()">
...
</form>
JS (inside the Angular controller):
$scope.registrationForm.confirmPassword.$setValidity("PasswordsMatch", $scope.validation.doPasswordsMatch);
I get the error that Cannot read property 'confirmPassword' of undefined
This leads me to believe that I have no access to the form registrationForm in the controller. Based on this (https://docs.angularjs.org/api/ng/type/ngModel.NgModelController) I imagined that I should.
Other solutions that I've seen include passing the form to the controller when the form is submitted, but what I need to do (set custom validation) needs to happen way before that.
Other solution mentioned adding the controller to the form via ng-controller but that changed nothing.
EDIT:
From the website above, is there a reason why in here (https://plnkr.co/edit/ZT0G6ajdbescT72qLKSU?p=preview) $scope.myForm can be accessed, but only inside of the $scope.setEmpty function?
I recommend using the controller itself instead of the $scope provider for this. This was one of the first issues I came across when working with angularjs
In your controller:
function MyController($scope) {
var vm = this;
vm.registrationForm.confirmPassword.$setValidity("PasswordsMatch", $scope.validation.doPasswordsMatch);
}
In your form:
<form name="vm.registrationForm" ng-submit="registerUser()">
...
</form>
The only gotcha is that you need to specify the controllerAs property in your route or ngInclude:
ng-include="templates/my-template.html" ng-controller="MyController as vm"
or
when('/my-route', {
templateUrl: 'templates/my-template.html',
controller: 'MyController as vm'
})
You need to add a name attribute to form element.
<form name="registrationForm" ng-submit="registerUser()">
...
</form>
this form must rely on a controller indeed. please take a look at the example:
angular.module("fooApp",[]);
angular.module("fooApp")
.controller("formctl",function(){
this.user={};
this.dosave=function(){
if(this.user.pwd == this.user.confpwd)
alert(this.user.username+" logged");
else
alert("pwd does not match");
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="fooApp">
<h1>sample</h1>
<div ng-controller="formctl as ctl">
<form ng-submit="ctl.dosave()">
<label>username</label><br/>
<input ng-model="ctl.user.username" required/><br/>
<label>password</label><br/>
<input ng-model="ctl.user.pwd" type="password" required/><br/>
<label>confirm password</label><br/>
<input ng-model="ctl.user.confpwd" type="password"/><br/>
<input type="submit"/>
</form>
</div>
</div>
You'll want to pass the form into the submit function to pass the entire form into the controller. Use the form name.
<form name="registrationForm" ng-submit="registerUser(registrationForm)">
...
</form>
The other option would be to pass the inputs directly in as params
<form name="myForm" novalidate >
some input: <input type="text" name="sometext" ng-model="myInput">
<input type="submit" ng-click="doAction(myInput)">
</form>
Quick Plunk
https://plnkr.co/edit/s0Al2LTHkvUPoLYNzTpm?p=info
If you're just after the value of the inputs, it's easier to test if you have explicit parameters that you expect on the method instead of dumping in the entire form.
I have a form inside an ng-if inside a controller with an ng-include, which doesn't submit...
I know ng-if and ng-include creates their own scopes, but I thought you could access controller methods..
index.html
<div data-ng-controller="myCtrl">
<div data-ng-include="form.html" data-ng-if="loadForm"></div>
</div>
form.html
<form action="" data-ng-submit="submit($event)">
<input type="text" name="foo" data-ng-model="foo">
<input type="submit" value="Go!">
</form>
ctrl.js
'use strict';
app.controller('myCtrl', function ($scope, $element, $http, $log) {
$scope.loadForm = true;
$scope.submit = function(e) {
e.preventDefault();
console.log("hello");
};
}
);
When I click on submit, nothing is logged into console, also e.preventDefault(); not firing...
I know the issue is scope hierarchy... I can't do data-ng-submit="$parent.submit($event)" because the form will be used elsewhere and form code needs to be reusable.
#Robert, you can use ng-show instead of using ng-if.
Because ng-if create/destroy the new DOM tree based on expression evaluation true/false respectively.
I am building an AngularJS application that includes modal windows which contain forms and are loaded into the DOM asynchronously (when the appropriate button is clicked). The forms work fine, but I cannot properly check if they are valid. Here's an example:
HTML
<div ng-app="myapp" ng-controller="MyCtrl">
<form novalidate name="myform" ng-submit="submitForm(myform)">
<input type="text" required ng-model="myname" />
</form>
</div>
JavaScript
var app = angular.module('myapp', []);
app.controller("MyCtrl", function($scope) {
$scope.submitForm(form) {
if(form.$valid) {
// Do http stuff here
}
};
});
If this form is loaded asynchronously, the form variable has value NaN and form.$valid is undefined. However, if I load it with the rest of the page, it works fine. Does anyone know how to force AngularJS to populate the scope variable for the form? Thanks!
When you include a form using ng-include a childScope is created. The parent and the childScope cant access eachothers scopes. Therefore the .$valid comes up empty.
I had a similiar issue the other day and got a working solution that suited me in this thread:
AngularJS $setValidity on childScope form
I'm trying to submit a standard form within an angular app.
Everything works well until I tried to add ng-click to the submit button of the form
The action on the click is just cosmetic to give the user some feedback.
The behavior I have is a bit strange. The submit is done and the call to the click behavior are both called, however, there is no parameters submitted with the form.
I've been googling a bit, and people seems to say that using ng-click on a form disable the submit, but it doesn't, Every works fine , except the form parameters which are not send.
I know I can probably redefine my own submit function, intercept the post using ng-submit and do the post myself, it just seems an overkill, as I want to do is almost working.
(in that case, how do you I get the form parameters from within the angular callback ?)
Update
Here is a live example : http://jsfiddle.net/hHapg/5/.If you check a box and submit, there is no parameter on the URL.
If you edit the file and remove the ng-click on the submit button, it works.
<form ng-app="test" action="/echo/jsonp" name="orders" target="_blank" ng-controller="test">
<table>
<tr ng-repeat="order in [{orderId:1}, {orderId:4}]" >
<td>
<input type="checkbox" name="order_ids{{i}}" value="{{order.orderId}}"></input>
</td>
<td>
{{order.orderId}} : {{ order.checked}}
</td>
</tr>
</table>
<input type="submit" name="action" value="Picking List" class="btn btn-primary picked" ng-clik="submit(true)">
</form>
Solution
Found the problem. Even though the real code wasn't exactly the one I published. with the help of Langdon I manage to solve it. The problem was I had an hardcoded array in the form declaration (not in the ng-repeat as in my example). (It was hardcoded from an angular point of view, but in fact generated at runtime). Moving this array to the top (same as ng-ap), solved the prome.
Are you setting the name attribute on all your input and select tags? I imagine most Angular examples do not include the name attribute because submitting forms seems a thing of the past.
The simplified example below works fine. I would need to see your specific code to help you troubleshoot what else the problem might be.
http://jsfiddle.net/langdonx/DUV9q/
HTML:
<form ng-app="test" ng-controller="test" action="/echo/jsonp/" method="get">
<input type="text" name="value1" ng-model="value1"/>
<input type="text" name="value2" ng-model="value2"/>
<input type="submit" ng-click="submit()">
</div>
JavaScript:
var app = angular.module('test', []);
app.controller('test', function ($scope, $http) {
$scope.value1 = "val 1 here";
$scope.value2 = "and val 2 here";
$scope.submit = function () {
alert('it should submit now, if it worked, you\'ll see some json');
}
});