Angular form validation not working with components - angularjs

I have the following form that is the template tied to a angular component. I'm able to retrieve the values tied to $ctrl.form when I submit which shows that the form is being tied to the controller, as expected, however, the $valid on the submit button does not work. Once I add the validator, the button always remains disabled as the form is not valid.
<div class="verification step-3">
<form name="form" ng-submit="$ctrl.submit()">
<fieldset ng-disabled="$ctrl.isSubmitting">
<md-content class="md-no-momentum">
<!-- username -->
<md-input-container class="md-icon-float md-block">
<label>Username</label>
<input data-id="login-username"
ng-model="$ctrl.form.username"
name="username"
type="text"
required>
</md-input-container>
<!-- register button -->
<div class="text-center">
<md-button data-id="register"
class="md-primary md-raised"
ng-disabled="!$ctrl.form.$valid"
ng-class="{ 'btn-disabled': !$ctrl.form.$valid }"
type="submit"
ng-click="$ctrl.submit()">
Create account
</md-button>
</div>
</md-content>
</fieldset>
</form>
</div>

remove the $ctrl from the $valid. $valid use to check the form validation so you don't need to use the controller as reference
change this
ng-disabled="!$ctrl.form.$valid"
to this
ng-disabled="!form.$valid"
remove the ngClick also since you are using ngSubmit
<md-button data-id="register"
class="md-primary md-raised"
ng-disabled="form.$valid"
ng-class="{ 'btn-disabled': form.$valid }"
type="submit"> Create account
</md-button>

Related

Show server side validation message in angularjs material md-input-container with ng-messages

I have a form with some inputs which are in md-input-container. Each input have some validation message with ng-messages directive:
<form name="ctrl.myForm" layout="column" ng-submit="addUser(model)">
<input hide type="submit" />
<div layout="column" layout-padding>
<md-input-container>
<label translate>Username</label>
<input name="username" ng-model="model.username" type="text" required>
<div ng-messages="ctrl.myForm.username.$error">
<div ng-message="required" translate>This field is required.</div>
<div ng-message="unique" translate>Username is used before.</div>
</div>
</md-input-container>
<md-input-container>
<label translate>Email</label>
<input name="email" ng-model="model.email" required>
<div ng-messages="ctrl.myForm.email.$error">
<div ng-message="required" translate>This field is required.</div>
<div ng-message="email" translate>Email is not valid.</div>
</div>
</md-input-container>
</div>
<div layout="row">
<span flex></span>
<md-button
class="md-raised"
ng-click="cancel()">
<wb-icon>close</wb-icon>
<span translate>Cancel</span>
</md-button>
<md-button
class="md-raised"
ng-click="addUser(model)">
<wb-icon>done</wb-icon>
<span translate>Add</span>
</md-button>
</div>
</form>
In my controller, I have a function named addUser(model) which send given data to server and receives some validation codes. I set appropriate keys in $error objects but relative messages are not show. I set keys as following if I get error from server:
function addUser(model){
$myService.newUser(model)//
.then(function(user) {
// user is created successfully.
}, function(error) {
ctrl.myForm.$invalid = true;
ctrl.myForm.username.$error['unique'] = true;
ctrl.myForm.email.$error['email'] = true;
});
}
I expect when I set keys as true related messages appear in the form but message are not shown. In this time if I change value of a field related message of that field is shown! I could not find problem.
Read here https://docs.angularjs.org/guide/forms about $asyncValidators, there are some examples also. (ctrl.$asyncValidators.username=... etc.)
In few words:
Angularjs built-in validation requires you to write and add validators. You should not control $invalid, $error fields manually (Thats why they have $ prefix).
Angularjs material also follow this approach.
P.S. reason why lines like ctrl.myForm.$invalid = true; wont work consistently is quite simple - angularjs next validation run will set it back to false

Checkbox value is not getting for button submit

I'm having a form with a text box and a checkbox. Checkbox is mutually exclusive. I want to pass the selected value when click submit button. Only the email value is getting and checkbox value is not getting. I'm totally new to Angular JS. Please help to fix this. This is what I tried
<ng-form name="manageForm">
<md-input-container class="md-block">
<label>E-mail</label>
<input required md-asterisk name="email" ng-model="manage.model.email">
</md-input-container>
<div ng-repeat="designation in $manageController.designations">
<md-checkbox ng-model="designation.checked" ng-change="$manageController.change(designation)">
{{ designation.name }}
</md-checkbox>
</div>
<div>
<md-button class="md-raised md-primary bm-button" ng-disabled="manageUsersForm.$invalid || manageUsersForm.$pristine" ng-click= "$manageController.submitUser(manage.email,designation.checked)">Submit</md-button>
</div>
Controller function
this.submitUser = function (email, designation) {
console.log(email, designation)
}
Change the way you are implementing checkbox
Use ng-checked instead of ng-model
<div ng-repeat="designation in $manageController.designations">
<md-checkbox ng-checked="designation.checked" ng-change="$manageController.change(designation)">
{{ designation.name }}
</md-checkbox>

"Required" validation not disabling submit in AngularJS

I have a form that is still running the submit code even if required fields have not been filled out. In Chrome it will pop up with "please fill out this field", but only on text inputs (not dropdowns) and it still runs the submit method. Am I missing something really obvious?
<form name="newForm">
<div class="section">
<div layout="row" class="inputRow">
<label for="itemA">ITEM A</label>
<input flex class="lineInput" ng-model="vm.contract.itemA" name="itemA" id="itemA" type="text" required />
<label for="itemB">ITEM B</label>
<select flex ng-model="vm.contract.contractType" name="itemB" id="itemB" required>
<option ng-repeat="type in vm.typeList">{{type}}</option>
</select>
<md-checkbox class="md-primary" aria-label="Checkbox No Ink" ng-model="vm.contract.itemC" name="itemC" id="itemC">
ITEM C
</md-checkbox>
</div>
<div layout="row" class="inputRow">
<label for="itemD">ITEM D</label>
<md-datepicker flex ng-model="vm.contract.itemD" id="itemC" name="itemC" md-placeholder="Enter date" required></md-datepicker>
<label for="itemE">ITEM E</label>
<md-datepicker flex ng-model="vm.contract.itemE" id="itemE" name="itemE" md-placeholder="Enter date"></md-datepicker>
</div>
</div>
<md-button type="submit" data-ng-click="vm.save()">Save and continue</md-button>
</form>
In your vm.save function inside the controller you have to put something like this:
if ($scope.newForm.$valid){
execute your code....
}
Hope it helps =)
If you want to disable Chrome doing it's own validation, and instead designing your own (for dropdowns for example) you need to include the novalidate attribute to your form.
Second, as Gustavo pointed out, your form has $valid/$invalid properties attached by angular, which can be used in many different ways:
Disable the save button:
<md-button ng-disabled="newForm.$invalid" type="submit" data-ng-click="vm.save()">Save and continue</md-button>
Moving the save function to the form using ng-submit
This allows you to submit by pressing enter, better than using ng-click IMO.
<form name="newForm" ng-submit="newForm.$valid && vm.save()">
Combining ng-disabled and ng-submit
<form name="newForm" ng-submit="vm.save()">
<md-button ng-disabled="newForm.$invalid" type="submit">Save and continue</md-button>
</form>
which is the best UX IMO
Using it to controller
if ($scope.newForm.$valid){
execute your code....
}

Form validation not working in mdDialog

I have this simple working form, but when I put this in a $mdDialog it doesn't disable the submit button anymore... it basically ignores the networktypeForm.$invalid Is this common or is there a fix for this?
<form name="networktypeForm" ng-submit="add()" novalidate role="form">
<div class="md-dialog-content">
<md-input-container md-no-float flex>
<label>Element type</label>
<input flex ng-model="type" name="networktype" type="text" required="">
<div ng-messages="networktypeForm.networktype.$error">
<div ng-message="required">This is required</div>
</div>
</md-input-container>
</div>
<md-dialog-actions layout="row">
<md-button type="submit" class="md-primary md-raised" ng-disabled="networktypeForm.$invalid">
Add
</md-button>
</md-dialog-actions>
</form>
your requireds should be like this required not required="" or required="required"
For those still looking at this, I had a similar issue and mine was solved by removing the "novalidate" attribute.

Autofocus an Input Element in AngularJs

I have a small search bar which is hidden initally. With a ng-click i set "filter.show" to true and the searchbar becomes visible. As soon as this happens i want the text input inside to be focused automatically.
I'm using Angular 1.5 and Angular Material and found the focus-me option as presented below. But this doesn't work somehow and I don't understand what's the problem. Maybe someone can help me.
The html presented below uses the same controller for the button and the input.
<md-toolbar class="md-table-toolbar md-default" ng-show="filter.show && !selected.length" aria-hidden="false">
<div class="md-toolbar-tools">
<md-icon md-svg-icon="magnify"></md-icon>
<form flex="" name="filter.form">
<md-input-container class="md-block" flex="" style="margin-bottom:0">
<label>Search</label>
<input type="text" focus-me="filter.show" ng-model="query.filter" ng-model-options="filter.options" aria-invalid="false">
</md-input-container>
</form>
<button class="md-icon-button md-button md-ink-ripple" type="button" ng-click="removeFilter()">
<md-icon md-svg-icon="close"></md-icon>
<div class="md-ripple-container"></div>
</button>
</div>
</md-toolbar>

Resources