AngularJs + Angular Material form is submitting twice - angularjs

I'm creating a registration form using AngularJs + Angular Material. Trouble I'm having is that when the form is valid and it is submitted, it is submitted twice. I cannot figure out why.
I'm not declaring the controller twice. The controller is declared only in the route provider.
I'm not using ngSubmit and ngClick simultaneously.
Html code for the form
<form
ng-submit="registerForm.$valid && performRegister()"
name="registerForm"
novalidate>
<md-input-container class="md-block">
<label>Name</label>
<input
type="text"
name="name"
ng-model="register.user.name"
required>
<div ng-messages="registerForm.name.$error">
<div ng-message="required">Inserisci il tuo nome</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<label>Email</label>
<input
type="email"
name="email"
ng-model="register.user.email"
ng-pattern="pattern.emailPattern"
required>
<div ng-messages="registerForm.email.$error">
<div ng-message="required">Inserisci la tua mail</div>
<div ng-message="pattern">Devi inserire una mail valida</div>
</div>
</md-input-container>
<p>
<md-button
type="submit"
class="button-block">Register</md-button>
</p>
</form>
Controller
SOS.controller("RegisterController", ["$scope", "$rootScope", "config",
function($scope, $rootScope, config) {
$scope.register = {
user: {
name: null,
email: null,
}
}
$scope.pattern = {
emailPattern: config.emailPattern
}
$scope.performRegister = function(){
console.log($scope.register.user);
}
}]);
Everytime i submit the form using the submit button, the performRegister() function is called twice, and i see the message in console twice.
If i submit the form using the Enter key it is submitted once.
Any idea why this is happening?
Thank you very much.

I had the similar problem in my application. This is what I have done to solve it.
I have added 'ng-click="performRegister()" (taking your code as example) in the md-button, & removed the same function from 'form' tag.
So finally it looks like:
<form
ng-submit="registerForm.$valid"
name="registerForm"
novalidate>
..
...
<md-button type="submit" ng-click="performRegister()"
class="button-block">Register</md-button>
Let me know, if this helps.

Related

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();
};

Server side validation for multiple fields in Angular

I have form where I need validation on server side. Backend use one request to validate multiple fields.
I try to add validation message after response. Here is example:
This is my html code:
<div ng-app="MyApp">
<div ng-controller="MyController">
<form name="MyForm" novalidate ng-submit="send()">
<div>
<label>Email</label>
<input type="email" name="email" ng-model="user.email" required>
<div ng-show="MyForm.email.$invalid">error message</div>
</div>
<input type="submit" ng-disabled="MyForm.$invalid">
<pre>{{ MyForm.email.$error | json }}</pre>
</form>
</div>
</div>
And my js code:
var myApp = angular.module('MyApp', []);
myApp.controller("MyController", ['$scope', '$timeout', '$log', function($scope, $timeout, $log) {
$scope.user = { "email" : "" }
$scope.send = function() {
$timeout(function() {
$log.log("Response from server. Multiple fields validation.");
$scope.MyForm["email"].$setValidity("server-side-error", false, $scope.MyForm)
// here I want to add something what listen once on $scope.MyForm["email"] changed
}, 1000);
};
}]);
But I need remove error when value changed. How to achieve it using Angular?
Here is example: https://jsfiddle.net/9wqhd89z/
You can call a check function whenever the user change the input using ng-change. So it will check if the email is currently invalid, and if it is it will set as valid again.
<input type="email" name="email" ng-model="user.email" ng-change="check()" required>
$scope.check = function(){
if ($scope.MyForm.email.$valid == false){
$scope.MyForm.email.$setValidity('server-side-error', true);
}
}
You can find a working version in this jsFiddle

value not getting updated in the controller

I am using a form control which has set of input boxes.
<form class="form-horizontal" role="form">
<input ng-model="editPagename" class="form-control" required/>
<input ng-model="editUrl" class="form-control" required/>
</form>
The value of editPagename is not getting updated in the scope and it's not even entering in the function.
$scope.$watch('editPagename', function(newVal, oldVal) {
console.log(newVal);
});
Do you have any suggestions on how to solve this problem?
try
$scope.$watch( function() {
return $scope.editPagename;
}, function(newVal, oldVal) {
console.log(newVal);
});
As it has been indicated that $scope will go bye bye in the future (you can have a read at this "preparing for the future of angularjs" on airpair, also a link the the youtube video of the ng-europe talk), and you might want to write your code for easy upgrading to 2.x
So, unless you absolutely need $scope for something, try this:
index.html
<body ng-controller="MainCtrl as vm">
<p>Hello {{vm.name}}!</p>
<div>
<form class="form-horizontal" role="form">
<input data-ng-model ="vm.name" data-ng-change="vm.checkValue(vm.name)" class="form-control" required/>
</form>
</div>
</body>
app.js
app.controller('MainCtrl', function() {
vm = this;
vm.name = "world";
vm.checkValue = checkValue;
function checkValue(value){
console.log(value);
}
});
And a plunker link with the example.
No $scope needed. And of what I can tell, does what you are asking.
Its working for me.Here what I have tried.
HTML :
<div ng-controller="testCtrl">
<form class="form-horizontal" role="form">
<input ng-model ="editPagename" class="form-control" required/>
<input ng-model="editUrl" class="form-control" required/>
</form>
</div>
JS :
app.controller("testCtrl",function($scope){
$scope.$watch( 'editPagename', function(newVal, oldVal) {
console.log(newVal);
});
})
Its logging in the console.
EDIT CODE :
Its better to use Objec model rather than primitive datatype.
Here is the code snippet.
HTMl
<div ng-controller="testCtrl">
<form class="form-horizontal" role="form">
<input ng-model ="objEdit.editPagename" class="form-control" required/>
<input ng-model="objEdit.editUrl" class="form-control" required/>
</form>
{{objEdit}}
</div>
JS :
app.controller("testCtrl",function($scope){
$scope.objEdit = {};
})

Cannot read property $valid of undefined

I have a form like this -
<form name="myForm" novalidate>
There are some fields in the form which I am validating and then submitting the form like this -
<input type="button" ng-click="Save(data)" value="Save">
In the controller, I want to check if the form is not valid then Save() should show some error on the page. For that, I am setting up a watch like this -
$scope.$watch('myForm.$valid', function(validity) {
if(validity == false)
// show errors
});
But I am always getting this error on running it -
Cannot read property '$valid' of undefined
Can someone explain why?
Thanks
You just misspelled "myForm" in your controller code. In order to remove the error, Write "myform" instead of "myForm".
However I expect what you want is like this.
$scope.Save = function(data){
alert($scope.myform.$valid);
}
I setup jsfiddle.
In my case I was wrapping the form in a modal created in the controller and therefore got the same error. I fixed it with:
HTML
<form name="form.editAddress" ng-submit="save()">
<div class="form-group">
<label for="street">Street</label>
<input name="street" type="text" class="form-control" id="street" placeholder="Street..." ng-model="Address.Street" required ng-minlength="2" />
<div class="error" ng-show="form.editAddress.street.$invalid">
<!-- errors... -->
</div>
</div>
<button type="submit" class="btn btn-primary" >Save address</button>
</form>
JS
angular.module("app").controller("addressController", function ($scope, $uibModal, service) {
$scope.Address = {};
$scope.form = {};
$scope.save = function() {
if (modalInstance !== null) {
if (isValidForm()) {
modalInstance.close($scope.Address);
}
}
};
var isValidForm = function () {
return $scope.form.editAddress.$valid;
}
});

Adding hidden form field to array in Angular

I am trying to add a "hidden" field to a basic form in Angular (using Firebase as the backend). I'm having trouble figuring out how to include this field as part of the array when the form is submitted. I want to include {type: 'Basic'} as part of the array. I've looked at the other related posts on this site, but am still unsure how to apply to my particular situation.
Any suggestions on how to do this?
Javascript:
myApp.controller('NewProjectCtrl', function ($location, Projects) {
var editProject = this;
editProject.type = 'Basic'; //this is the hidden field
editProject.save = function () {
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
});
HTML:
<form>
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="editProject.project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="editProject.project.description"></textarea>
<button ng-click="editProject.save()" class="btn btn-primary">Save</button>
</form>
You don't need a hidden form field, just submit your value in your controller like this:
editProject.save = function () {
editProject.project.type = 'Basic';
Projects.$add(editProject.project).then(function(data) {
$location.path('/');
});
};
All attributes of your editProject.project will be submitted, as you may notice in the developer console.
I would structure the controller a bit different.. here is an example (I am considering you are using angular-resource, where Projects returns a Resource?):
myApp.controller('NewProjectCtrl', function ($location, Projects) {
$scope.project = new Projects({type: 'Basic'});
$scope.save = function () {
$scope.project.$save().then(function(data) {
$location.path('/');
});
};
});
<form ng-submit="save()">
<div class="control-group form-group">
<label>Name</label>
<input type="text" name="name" ng-model="project.name">
</div>
<label>Description</label>
<textarea name="description" class="form-control" ng-model="project.description"></textarea>
<input type="submit" value="Save" class="btn btn-primary" />
</form>
The save function will $save the new project resource (this is an default method and will make a POST on the given resource URL).

Resources