I have the html below where I have a form that I want to submit to the AngularJS Controller.
<div class="newsletter color-1" id="subscribe" data-ng-controller="RegisterController">
<form name="registerForm">
<div class="col-md-6">
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe">
</div>
<div class="col-md-2">
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block">Subsbcribe</button>
</div>
</form>
</div>
And the controller is below
app.controller('RegisterController', function ($scope,dataFactory) {
$scope.users = dataFactory.getUsers();
$scope.register = function () {
var userEmail = $scope.userEmail;
dataFactory.insertUser(userEmail);
$scope.userEmail = null;
$scope.ThankYou = "Thank You!";
}
});
The problem is that no validation is taking place when I click the button. It is always routed to the controller although I do not supply a correct email. So every time I click the button I get the {{ThankYou}} variable displayed. Maybe I do not understand something.
AngularJS does not disable enable any functionality for form validations. What is does is, it makes the state of the form and its control in terms of validation available on the current scope. You are required to implement the behaviour yourself.
In your case if you need to check user email is valid your html input should have a name attribute like
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required class="subscribe" name='userEmail'>
Then on your controller you can check
$scope.registerForm.userEmail.$invalid property.
You can use the same property to disable the button on the form using ng-disabled
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled='registerForm.userEmail.$invalid'>Subsbcribe</button>
Basically the registerForm object is a ngFormController and userEmail is ngModelController. Please read the developer guide for forms
You are missing some part to achieve what you want. Normally you will need to add some code to enable disable the submit button base on the state of the form i.e valid/invalid. In your case this can be done like that :
<button data-ng-click="register()" class="btn btn-primary pull-right btn-block" ng-disabled="registerForm.$invalid">Subsbcribe</button>
Notice the ng-disabled="registerForm.$invalid".
You can as well provided inline feedback to the user with something like :
<input type="email" placeholder="your#e-mail.com" data-ng-model="userEmail" required="" class="subscribe" name="userName"/>
<span ng-show="registerForm.userName.$error.required">Please enter a name</span>
Or with CSS like that :
input.ng-invalid-required {
background-color: #FA787E;
}
You have a working plunker here
Related
I have a form which when I submit, I reinitialise it as the form has been submitted. I then show a message and stay on the same page.
However, the form's fields come up with the error messages as the form has been "touched".
Demonstrated below:
I have read some articles about how to go around this but none are working for me.
My HTML:
<form name="newPost" ng-submit="makeNewPost()">
<div class="form-group">
<input name="title" maxlength="46" minlength="2" type="text" class="form-control" ng-model="post.title" required="required">
<div ng-messages="newPost.title.$error" ng-if="newPost.title.$touched">
<div class="errorMessage" ng-message="required">Title is mandatory *</div>
</div>
</div>
<input type="submit" value="Submit" class="btn btn-success" id="submit">
My controller code to reset the data:
var resetData = function(){
$scope.post = {};
};
resetData();
Of course there are more fields but to solve the problem, just this simple code will demonstrate it.
Any input will help. Thanks chaps!
Your resetData function should be:
$scope.resetData = function(){
$scope.post = {};
$scope.newPost.$setUntouched();
$scope.newPost.$setPristine();
}
where newPost is form name & $setUntouched, $setPristine will make form pristine just like initially loaded. Call this function in the end of submit function.
In this plunk I have an Angular UI date picker with an error message that is displayed when the date is invalid. Problem is that the error message is shown below the date instead of the same line. How to fix this?
HTML
<form name="form1" ng-submit="validate(form1)" novalidate>
<p class="input-group" style="width:160px;margin-bottom:0px;">
<input type="text" class="form-control" ng-model="dtFrom"
is-open="config1.opened" uib-datepicker-popup="MM-dd-yyyy"
close-text="Close" name="dtFrom" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1($event)">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
<div style="background-color:red;color:white;width:150px"
ng-show="!form1.dtFrom.$valid">Invalid Date</div>
</form>
Javascript
var app = angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
app.controller('ctl', function ($scope) {
$scope.dtFrom = new Date ();
$scope.config1 = {};
$scope.config1.opened = false;
$scope.open1 = function(event){
event.preventDefault();
event.stopPropagation();
$scope.config1.opened = true;
};
});
You can add class list-inline in it.
Here is plnkr
http://plnkr.co/edit/23CxCMDRK6DBiW115K7T?p=preview
The reason you are seeing this misalignment is because you are using bootstrap classes but are not correctly applying them to all the corresponding elements. When you use an input-group as you've applied to the <p> element, you are using a specific bootstrap class that adds styling to the components, like display:table. To have a correct behavior for the whole form, you need to keep using these classes on sibling elements. Namely input-group and form-control. Using these you will notice that its better aligned to its neighbor in both position and height. Additionally its best to wrap all these components in a valid row and column classes for parent elements. I've added an updated version of your plnkr showing how these changes behave:
plnkr
I am trying to make a search function which works if I put in the query params into my URL directly but I don't know how to make it work so that it picks it up from the search box and executes it. I have used ng-model to map the text itself to the controller which works but the execution isn't working.
The navbar form:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
By the way, my doSearch() function works just fine when I run it manually and so is the search itself. I have also validated that search.text comes through. I guess what I am asking is how do I make the icon (glyphicon-search) execute ng-submit="doSearch()" when the user clicks on it or presses enter.
Sorry if this is very obvious. I was always more on the backend side of things so am sorta new to HTML and Angular.
Thanks
You could place the icon inside a <button> element instead of <span>, tweak a bit of css to integrate it to the form field.
In regards to trigger search on enter, with jQuery something like this could be used:
$('input').keypress(function (e) {
var key = e.which;
if(key == 13) // the enter key code
{
doSearch();
}
});
did you try using <button type="submit"> before your search icon
<span class="glyphicon glyphicon-search"></span>
to specify that clicking on that button is equivalent to a submit event for that form.
So this worked in the end. First, the proper HTML which works:
<form ng-submit="doSearch()" class="navbar-form">
<div class="form-group" style="display:inline;">
<div class="col-md-offset-4 input-group" style="display:table;">
<input ng-model="search.text" class="form-control" name="search" placeholder="Search Here" autocomplete="off" autofocus="autofocus" type="text">
<span ng-click="doSearch()" class="input-group-addon" style="width:1%;">
<span class="glyphicon glyphicon-search"></span>
</span>
</div>
</div>
</form>
Furthermore, there was an issue with the view not connecting to the controller. Actually, let me rephrase that - it was connecting to the controller but only when the whole page loaded and for my test, I had a console.log('I have loaded') put in there. So when I saw "I have loaded", I thought my controller was invoked properly.
However, the doSearch() was in the controller which was connecting via angular routing, so the ng-View was not connecting to the right controller.
I am not sure if this means anything to anyone but I am writing this in case someone else comes across an issue like mine.
So just to summarise the issue was not with the HTML as I originally thought. ng-submit (for form submission when pressing enter) and ng-click (for clicking the glyphicon) does the trick.
I am trying to submit a form, but the values are always empty.
my HTML:
<form novalidate name="creditCardForm" id="creditCardForm" method="POST">
<input type="hidden" name="EPS_MERCHANT" value="{{credit.data.merchantId}}">
<input type="hidden" name="EPS_TIMESTAMP" value="{{credit.data.currentGMTTimestamp}}">
<input type="hidden" name="EPS_TYPE" value="{{credit.data.epsType}}">
<div class="text-center">
<button class="btn btn-primary" ng-click="credit.save()">Save</button>
</div>
</form>
and my js part:
function save(){
document.getElementById("creditCardForm").setAttribute("action", this.data.crnUrl)
document.forms["creditCardForm"].submit()
}
and from inspection, these fields all have values
but from the request, these fields are all empty:
update my question:
because this is a special form post that it will call NAB bank api to verify something, so I cannot put each fields into an object and do a ajax/$resource/$http call.
thanks
That's a not angular way to submit the form via action attribute. Use ng-submit form attribute and make a $http.post request async.
<form novalidate name="creditCardForm" id="creditCardForm"
ng-submit="saveCredit(creditCardForm)">
<!-- no input hidden -->
<div class="text-center">
<button class="btn btn-primary">Save</button>
</div>
</form>
And you dont need hidden inputs in this way.
If I get your question and your requirement correct. You should be using following way:
<form novalidate name="creditCardForm" id="creditCardForm" method="POST">
<input type="hidden" name="EPS_MERCHANT" ng-model="credit.data.merchantId">
<input type="hidden" name="EPS_TIMESTAMP" ng-model="credit.data.currentGMTTimestamp">
<input type="hidden" name="EPS_TYPE" ng-model="credit.data.epsType">
<div class="text-center">
<button class="btn btn-primary" ng-click="credit.save(credit.data)">Save</button>
</div>
</form>
This is assuming that credit is the alias for your controller.
I have tried to keep your ways of ng-click to call a method on controller. However with forms in angular, you can do the same via ng-submit directive also.
In your controller you will have something like:
$scope.save = function(data){
//use data here as you like
//data.merchantId and other fields
}
If you are using alias form, then use:
//vm or any other name you have for your `this` instance
vm.save = function(){
// use data here as you like
}
I want to try to fix your problem. The first thing that you have to do is add ng-model and ng-value in your form. For example:
view:
<form novalidate name="creditCardForm" id="creditCardForm" ng-submit="save()">
<input type="hidden" ng-model="credit_card.eps_merchant" name="eps_timestamp" ng-value="{{credit.data.merchantId}}">
<input type="hidden" ng-model="credit_card.eps_timestamp" name="eps_timestamp" ng-value="{{credit.data.currentGMTTimestamp}}">
<input type="hidden" ng-model="credit_card.eps_type" name="eps_type" ng-value="{{credit.data.epsType}}">
<div class="text-center">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
For the next you can create controller. For example:
angular controller:
angular.module('cartApp')
.controller('AddCreditCartCtrl', [
'$scope',
'$location',
'$http',
function($scope, $location, $http) {
$scope.credit_card = {};
$scope.credit.data = {
merchantId: 'your-merchant-id',
currentGMTTimestamp: 'your-currentGMTTimestamp',
epsType: 'your-epsType'
}
$scope.save = function () {
$http.post('/yourUrl', {credit_card: $scope.credit_card}).then(function(res){
// Successfully create data
},
function(response) {
// Failed to create data
});
}
}]);
I hope this can help you. :)
thanks every body above. just want to share the root cause
I have a directive called <credit-card></credit-card>, and inside this directive, I have the form, with both name and id to be creditCardForm, so when this directive is used in several places, and in the controller I use document.forms["creditCardForm"], js did not know which is the target form, and this results in empty values in the request
hope it can help someone with same problem
<div ng-app>
<div ng-controller="Ctrl">
<form ng-submit="submit() ">
<textarea ng-model="text" required></textarea>
<div ng-click="submit()" style="background-color:#ff00ff;cursor:pointer;width:100px;">Create !</div>
<button type="submit" style="background-color:#ff00ff;cursor:pointer;width:100px;">Create !</button>
</form>
{{list}}
</div>
</div>
I want to submit an Angular form with a custom div button but when I do it like above, the "required" statements are not taken into account like it is done for the button.
When the textarea is empty the first button runs the submit() function anyway.
Is it possible to have the same behavior as the button ?
Here is a JsFiddle illustrating this:
http://jsfiddle.net/xKkvj/55/
I think you should be using an input rather than a div, eg:
<input type="submit" ng-click="submit()" style="background-color:#ff00ff;cursor:pointer;width:100px;">Create !</input>
I've tested it on your jsFiddle, and it works fine.
If you really must use a <div>, use it to wrap the <input>
UPDATE
It looks like you can't use anything other than an input or a button as that is what ngForm listens to for form submission. You could either extend ngForm or you could use a hidden button and trigger that from your div like so:
<div onClick="document.getElementById('hiddenButton').click();" style="background-color:#0000ff;cursor:pointer;width:100px;">Create !</div>
<button id='hiddenButton' type="submit" style="display:none;">Create !</button>
jsFiddle here. Hopefully this'll do the trick for you.
If you want to submit form from a div element, then you should manually test if form is valid in your submit handler:
function sumbit() {
if (form.$invalid) {
return;
}
// Other code...
}
The point is that when you submit your form via <input type="submit"/>, then form validation check is performed internally & form handler do not invoked in case of invalid form.
UPDATE
Your jsfiddle form handler should look like:
$scope.submit = function () {
if ($scope.submitCreateSurveyForm.$invalid) {
return;
}
if ($scope.text) {
$scope.list.push($scope.text);
$scope.text = '';
}
console.log("sent");
};