form submitted when dynamically adding fields with ng-repeat - angularjs

I am dynamically creating form fields using ng-repeat. I have a div with several inputs/selects and when I click an "add" button, they gets duplicated. No problems so far. However, I also want to perform form validation when the submit button is clicked. Right now, I am doing the following to alert users a field is invalid when the submit button is pressed:
.ng-submitted select.ng-invalid, .ng-submitted input.ng-invalid {
background-color: red;
}
This works as expected provided I have not dynamically added inputs to the form. If I add new inputs to the form, .ng-submitted gets added to my form element (without submit being pressed) and all the required and invalid inputs turn red. You can see an example of this here: https://plnkr.co/edit/hDe40mBDjw9aDSDoAhe6?p=preview
Not only do I not want the inputs turning red when simply adding elements, I also don't want the form submitting unless someone has hit the submit button. There must be something I don't understand about submit with angular forms and help would be appreciated.
EDIT: further testing shows that the button element is the problem.
<button ng-click="addRow()">add</button>
This works fine however:
<input type="button" ng-click="addRow()" value="add"/>
Not sure why this is though.

The default value of the type of a button is "submit". So clicking it submits the form. Putting type="button" explicitly prevents the form being submitted when the button is clicked.

If you want to use form submit you need to use ng-submit on form and change button type to submit.
<form name="form" ng-submit="addRow()">
<div>
<div ng-repeat="row in rows track by row.id">
<input type="number" min="0" ng-model="row.id" required/>
</div>
<button type="submit">add</button>
</div>
</form>
There were multiple changes needed in your code. I have fixed them in this plunker: https://plnkr.co/edit/GEWdCo1cQPPEFJcZxT58?p=preview

Related

AngularJS - validation not based on form element

Is there a way to inject some validation - custom or otherwise - that isn't tied to a form element? Like - validate that some condition is met, but have it work with standard AngularJS validation?
Update:
Here's what I'm trying to accomplish:
I have a form contains a list of sections. Each section is controlled by a checkbox, and the section will display (via an ng-if) when the checkbox is checked.
Within each section, there's an opportunity for an item to be selected via a popup modal that is activated by a button click. Until an item is selected for that section, the form needs to be invalid. Once an item is selected for each selection that is checked, then the form needs to be valid.
I have a button at the bottom of the form with an ng-disabled="frm.$invalid". I want that to stay disabled until each section that has been checked contains an item that was selected via the modal.
Update 2:
Here's some example code:
<form class="form-horizontal" role="form" name="frm" novalidate>
<label>Name: </label>
<input type="text" ng-model="name" required/>
<div ng-repeat="orderItem in orderItems">
<input type="checkbox" name="items[]" ng-model="orderItem.selected"/>
<div ng-if="orderItem.selected">
... bunch of form fields
<button ng-click="openExchangeSelectionModal(orderItem)">Select Item</button>
<div ng-show="orderItem.exchange_item">
Selected Item: {{orderItem.exchange_item.name}} - ${{orderItem.exchange_item.price | number: 2}}
</div>
</div>
</div>
<button ng-disabled="frm.$invalid" ng-click="submitOrder">Submit</button>
</form>
Checking if the form is valid won't help you in this case since there is no required input that's not being filled.
What I would recommend is that the disable button would call a function that makes some logic about the number of check boxes expanded and the number of selected items and returns the buttons state (true for active otherwise false)
Let's take the example code you put up:
//some html tags...
<button ng-disabled="checkValid()" ng-click="submitOrder">Submit</button>
</form>
Notice that I changed the frm.$invalid to checkValid function, which is a function that is defined on your controller and can perform any logic you want to determine rather show your submit button or not.

How to reset a form in AngularJS

I'm working in AngularJS with a very simple form that only has a textarea input and a submit button. The textarea is a required field. Everything works... until I've submitted the form. When I remove the value from the model after submitting the form, this triggers my validation errors. If I don't set the value to null or an empty string, the textarea retains the entered value, which is not what I want.
<form name="notesForm" class="form-horizontal" ng-submit="vm.addNotesForm(notesForm)" novalidate>
<div control-validator="" validator-condition="vm.hasTriedToSubmit">
<div class="col-sm-10">
<!-- hidden field workaround for validation for textarea -->
<input type="hidden" id="hiddenNewNote" name="hiddenNewNote" required ng-model="vm.newNote.note" />
<textarea id="newNote"
name="newNote"
class="form-control"
placeholder="Note"
ng-disabled="vm.isWorking"
ng-model="vm.newNote.note"
rows="3"></textarea>
<control-validator-message>Note is required.</control-validator-message>
</div>
<div class="col-sm-2">
<button class="btn btn-success" type="submit" ng-disabled="vm.isWorking">
<i class="fa fa-save"></i>
Add Note
<i class="fa fa-circle-o-notch fa-spin" ng-show="vm.isWorking"></i>
</button>
</div>
</div>
Since validation only works for input fields, the hidden field is necessary.
this.notesService.addNote(this.newNote).then(() => {
this.notificationService.success('Successfully added new AR Note');
this.isWorking = false;
this.newNote.note = null; // <- This is where it goes sideways.
this.refreshDataTable();
}, errorMessage => {
this.notificationService.error(errorMessage);
this.isWorking = false;
});
I've tried all sorts of solutions. I used the FormController to set the form to pristine and untouched - no luck. I saw a proposed solution where the controls on the form were programmatically set to 'undefined'. Still no luck. Either the form submits and my value stays there in my textarea, or I set the note to null/empty string, and the validation errors get set off as if I've tried to post without a value in the textarea. As a total hack I even tried using jQuery to set the value of the textarea to an empty string, while keeping the model state undisturbed. While this did appear to work, since the value is still stored in the model, if a user clicks the add button again, it reposts. Not what I need. I'd think this would be a cinch, but after an hour of looking for an answer online, I've come up with nothing that works.

Display validation messages when a button is clicked

I think what I want to achieve is quite simple. Let's have a form with a required field, a select for instance (I've also tried it with an input and it's exactly the same situation anyway).
I want to display the ng-messages only when a button is clicked. If the form field was touched before clicking the button, it works fine. But I cannot do it if the form field is $untouched.
I've solved it setting programatically $touched to the form field, but I'm wondering if there is any way to solve it without this uggly 'hack'.
// Any way to avoid this line??
$scope.myForm.favoriteColor.$setTouched();
//
Code for reference:
HTML:
<md-input-container>
<label>Favorite Color</label>
<md-select name="favoriteColor" ng-model="favoriteColor" required>
<md-option value="red">Red</md-option>
<md-option value="blue">Blue</md-option>
</md-select>
<div class="errors" ng-messages="myForm.favoriteColor.$error" ng-show="validateWithHack">
<div ng-message="required">Required</div>
</div>
</md-input-container>
JS:
$scope.validateWithHack = function() {
if ($scope.myForm.$valid) {
alert('Form is valid.');
} else {
// Any way to avoid this line??
$scope.myForm.favoriteColor.$setTouched();
//
$scope.validateWithHack = true;
}
};
I'm pretty sure that this was working with previous versions of angular-material. Now I'm using the latest 1.1.1.
Here is a plunker where the
problem can be easily reproduced.
Thanks in advance.
Check the CodePen
I have added novalidate to your form and added type="submit" to your md-button
Edit 2:
The type="submit" button actually triggers a form submit and so the angular form validates itself first, What we need to do is to prevent the submit and just do the validation.
novalidate(Just to supress the HTML5 validation) to your form and added type="submit" to your md-button : This Will Validate the form and submit the form, To validate and prevent form submit add ng-click="submitMethod(<yourForm>, $event)" to the <md-button> and define method as
$scope.submitMethod(form,ev){
ev.preventDefault();
//rest of your form work say if you want to do ajax or anything you like
//check if form valid using form.$invalid
}

Show a Button on ng-form change

I have an ng-form="step1" which is populated with data from db.
When the user changes some thing in the input boxes or selects a different radio btn, I want to display a Update Button.
This button will be hidden at first.
How to do this?
Thanks for Help
use $dirty function of angularjs
example
<input type="button" class="btn btn-primary" value="update" ng-show="changedetect.$dirty" />

Angularjs default action when Enter key is pressed

My understanding with forms, is that if the form has an ng-submit action associated with it, then pressing the Enter key would invoke that action, typically mimicking the click of the form's "submit" button. I have a form that does not have have a button, but a custom image of a button within a div tag and the div tag has the ng-click action. When I press Enter, nothing happens. What am I missing?
Make your button type submit and add a class attribute and style your button to make it an image like:
<form ng-submit="someAction()">
<button type="submit" class="submitbutton">Submit</button>
</form>
And do style your button in css like:
.submitbutton {
background:url('....') // your custom image
}
Then your custom image will act as the submit button and invoke the form action when click the enter key.
It worked for me by adding ng-submit, ng-controller & button type as submit
<form ng-submit="func()" ng-controller="MyController">
<button type="submit">Submit</button
</form>
if your form contains md-autofocus - remove it.
worked for me.
For Angular 13:
<form (ngSubmit)="search()">
<input type="text" id="inputword" />
<button type="submit" id="send" class="btn btn-lg btn-primary">Search</button>
</form>

Resources