AngularJS: Required form field not woking with ng-click submit - angularjs

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

Related

Can a form be invoked on a click event in AngularJS ?

I am creating a project to put into practice what I have learned about AngularJS. I created a form, which uses a controller. In the form, I have a button to save the information filled in by the user. After the information is save into the database I would like to call a second form to continue, (this form has its own controller) etc. How can I do that ?
If you're not navigating to a different view, you probably dont need another controller. You can show and hide forms conditionally with ng-if. Ie. say first form is done, you've posted it to the database. You can do something like this
$scope.form = 1
<form id="form1" ng-if="form === 1">
//your form html
</form>
<form id="form2" ng-if="form === 2">
//your form html
</form>
then when form1 is submitted, you can do
$scope.form = 2
in your controller to hide the first form and render the second one
If you're set on the different forms having different controllers, you can do something like this
<div controller="mainCtrl">
<form controller="form1Ctrl" id="form1" ng-if="form === 1">
//your form html
</form>
<form controller="form2Ctrl" id="form2" ng-if="form === 2">
//your form html
</form>
</div>
You would set the form variable from the mainCtrl's scope
You can use ng-submit for this:
<form ng-submit="goToNextForm()">
<input type="text" ng-model="email">
<button type="submit" value="submit">
</form>
And in controller:
$scope.goToNextForm = function(){
//code to save data and move to next controller/form here
}

Fire a method when click an Enter key

<form novalidate name="frm1" autocomplete="off">
//UI elements
<div class="col-sm-3 col-sm-offset-6">
<button ng-click="MyFunc()">Next Step</button>
</div>
</form>
Can you tell me how to fire MyFunc() method when click the enter key.On the above form where there is no submit button. Thanks in advance.
Try this:
<input ng-keyup="$event.keyCode == 13 ? MyFunc() : null" >
At form level you can use this:
<form ng-submit="myFunc()" ...>
I have written below mentioned directive and it works.
Directive :
angular.module('app.directives')
.directive('ngEnter', function () { //a directive to 'enter key press' in elements with the "ng-enter" attribute
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if (event.which === 13) {
scope.$apply(function () {
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
})
HTML
<form novalidate name="frm1" autocomplete="off">
//UI elements
<input name="userName" type="text" ng-enter="MyFunc()"/>
<div class="col-sm-3 col-sm-offset-6">
<button ng-click="MyFunc()">Next Step</button>
</div>
</form>
Simply write (keyup.enter)="your_function_name()" in your html file in same way you write (click).
Below is a code snippet.
<input type="text" [(ngModel)]="modelSearchedData" (keyup.enter)="getModelList()">
What you should do is binding your function on submit event instead of enter key. You should not focus on enter, because for exemple on the iPhone there is a keyboard button to execute form, which behave like enter but is not enter event ... and the iPhone is just one exemple :D
So you should change your <button> by an input <type="submit"/>
This way enter key will automatically fire the form submit event.
Then in your submit event, return false; to prevent HTML action (which send the form) and execute your code.
HTML
<form novalidate name="frm1" autocomplete="off">
//UI elements
<div class="col-sm-3 col-sm-offset-6">
<input type="submit" value="Next Step" />
</div>
</form>
JS
$('form').submit(function () {
MyFunc();
return false;
});
I hope this answer your question.
PS : you can use ng-submit instead of jQuery selector, if you do not want to use jQuery.
I found a solution that does not require a directive. I was already using ng-change to capture each keypress and perform a search, but clicking Enter would throw my SharePoint page into Edit mode. SharePoint doesn't let you access the form tag, so most of these solutions didn't work for me.
This solution was much simpler and kept my code in the same place, I have an ng-change AND an ng-keypress event that point to the same event handler, vm.txtSearchChange():
HTML
<input id="txtSearch" type="text" style="width: 400px;" ng-change="vm.txtSearchChange()"
ng-keypress="$event.keyCode == 13 ? vm.txtSearchChange($event) : null"
ng-model="vm.Search" ng-model-options="{debounce: 200}"/>
Note the ng-change event does not pass the $event attribute, and handles the legitimate key presses, while the ng-keypress event is only for the enter key.
SCRIPT
vm.txtSearchChange = function ($event) {
if ($event) {
$event.preventDefault();
return;
}
console.log("Search: " + vm.Search);
vm.showResults();
} // end vm.txtSearchChange
When $event is not null, it's the enter key, we call preventDefault() and don't process further. When $event is null, it's a valid key, and we pass it along to vm.showResults() for processing.
Most of the answers here involve additional workarounds that simply are not needed, you can work with the standard form submission by making these two small changes and the Enter key will function as desired.
Move the ng-click from the button to the form, and make it an ng-submit
Add a type="submit" to the button
For more complex forms with multiple buttons you might need to try some of the workarounds, but for the majority of cases this will work.
<form novalidate name="frm1" autocomplete="off" ng-submit="MyFunc()">
//UI elements
<div class="col-sm-3 col-sm-offset-6">
<button type="submit">Next Step</button>
</div>
</form>
<input type="text" name="Inputvalue" id="Inputvalue" ng-change="EnableDisableCheckButton()" ng-model="enteredInputValue" ng-disabled="isDisabledInputvalueTextbox" ng-blur="" data-ng-keypress="onEnterKeyPress($event)" />
<button type="button" class="btn btn-primary" ng-disabled="isDisabledCheckButton" ng-click="ValidateInputvalue()">Check</button>
And in your JavaScript file, add below:
$scope.onEnterKeyPress = function (event) {
if (event.charCode == 13) //if enter is hot then call ValidateInputvalue().
$scope.ValidateInputvalue();
}
This example worked for me:
HTML Code:
<input matInput type="text" [(ngModel)]="searchString" ng-change="startSearch()" ng-keypress="$event.keyCode == 13 ? startSearch($event) : null">
Typescript:
#HostListener('document:keypress', ['$event'])
startSearch(event: KeyboardEvent) {
if (event.code === "Enter") {
//Code that you need to run
}
}
https://go.tiny.cloud/blog/angular-5-tutorial-step-step-guide-first-angular-5-app/

event.preventDefault with Firefox and AngularJS

I know there are lot of threads with this question but mine is a little different I will explain why.
Background:
I am using angular JS to submit a form. I have a groovy tags like below in my GSP
<form action="formAction" class="form-horizontal" id="UserForm" name="UserForm"
useToken="true" ng-app="angularApp" ng-controller="angularController" novalidate="" ng-submit="onSubmitClick();">
<input type="button" name="next" value="submit"
id="submit" />
( Actually a submit tag in Groovy but StackOverflow doesnt allow me to write that )
This is a form tag with Action and ng-submit specified.
What I am trying to achieve:
When the submit button is clicked "onSubmitButtonClick()" function is invoked and if the form is invalid it needs to prevent submit.
onSubmitButtonClick is defined in angular Controller. Now the problem is Angular JS will submit the form as long it finds the "action" URL defined. I cannot remove value for that URL because it is coming from serverside at run time. so I started using event.preventDefault().
event.preventDefault doesnot work in Firefox so I started passing event in function call onSubmitButtonClick(event) and I realize that for Firefox this comes as undefined.
So, is there a way to access event in firefox ? I cannot use 'return false' or event.returnValue=false because Angular just ignores them. So, I need to get event.preventDefault to work.
Below is how onSubmitButtonClick code looks like :
$scope.onSubmitButtonClick=function(evt){
if($scope.UserForm.$invalid)
{
var browserObj=browserDetectFunction();
if(browserObj.browser=='Firefox')
{
evt.preventDefault(); // this throws evt undefined error in Firefox
} else
{
event.preventDefault();
} } }
Any help is appreciated. Thanks
Not exactly answering your question, but a different route to take that should work (looking at your code):
<input type="button" name="next" value="submit"
id="submit" ng-disabled="UserForm.$invalid" />
Or you remove your submit button if invalid, and replace it with a non-functioning button:
<input type="button" name="next" value="submit"
id="submit" ng-if="UserForm.$valid" />
<button type="button" name="next" value="submit"
ng-if="UserForm.$invalid" />

AngularJS Dynamically Adding Control In Repeater to Form Causes Submit

I have a form which represents an object and an array of sub-objects contained in a repeater. I want to dynamically add sub-objects to the array. When I add a sub-object the form gets submitted unexpectedly.
See this example:
http://plnkr.co/edit/TUblgmb7N710nPL7s5tU?p=preview
My form looks like this:
<form ng-submit="handleSubmit()" ng-controller="TestController">
<div>Some Input: <input type="text"></div>
<div ng-repeat="obj in model.children">
<input type="text" ng-model="obj.text" />
</div>
<button ng-click="addChild()"> Add Child</button>
</form>
The controller looks like this...
Controllers.controller('TestController', ["$scope", function($scope) {
$scope.model = {
name: "Some Text",
children: []
};
$scope.handleSubmit = function() {
alert("Form Submitted!");
}
$scope.addChild = function() {
$scope.model.children.push({text:"Foo"});
}
}]);
Click the "Add Child" buttton. The UI is updated as expected but the form gets submitted.
I can work around this by putting the submit function in ng-click on the Save button instead of ng-submit on the form but this seems like unexpected behaviour. Can anyone explain?
The default attribute type The HTML button tag <button>My Button</button> triggers the submit event as <input type = "submit"...> does.
Now, following the idea of #GruffBunny, I have added a pInputType parameter to your method to show what button was clicked:
$scope.addChild = function(pInputType) {
$scope.model.children.push({text:"Foo", inputType : pInputType });
}
Then in the HTML block, the attribute inputTypewas added within the loop as follow:
<div ng-repeat="obj in model.children">
<hr />
<h3>{{obj.inputType}}</h3>
<div>New Input: <input type="text" ng-model="obj.text" /></div>
</div>
Finally, here are the buttons for testing the code:
<!-- With Input Type -->
<h2>Input type Button</h2>
<input type="button" ng-click="addChild('Input type Button')" value="Btn Add Child" />
<hr />
<!-- With Normal Anchor -->
<h2>HTML Anchor</h2>
Add Child Link
<hr />
<!-- Adding Bootstrap -->
<h2>HTML Bootstrap Anchor</h2>
Add Child Link
<hr />
<!-- Button Tag -->
<h2>HTML Button Tag (Triggers SUbmit Events)</h2>
<button ng-click="addChild('Triggers Submit Events')">Add Child</button>
<hr />
Here is the complete plunker: http://plnkr.co/edit/N4hSjG
For further information about this behavior, you can read this Stack Overflow question: <button> vs. <input type="button" />. Which to use?
I hope it could be useful this explanation for anyone.

AngularJS not validating email field in form

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

Resources