I'm new to angular and trying my hand at directives.
I would like to be able to use
<div ng-messages="form.$error">
<div ng-message="required">You did not enter a field</div>
</div>
Within a custom directive like so,
<div class="form-group">
<label class="form-label" for="s-input-{{name}}">
{{text.human}}
<span ng-if="text.subtext" class="form-hint">{{text.subtext}}</span>
</label>
<select ng-required="required" ng-model="model" class="form-control" id="s-input-{{name}}" name="{{name}}" ng-options="t for t in text.select"></select>
<div ng-messages="form.$error">
<div ng-message="required">You did not enter a field</div>
</div>
</div>
I can get it to work by passing using ng-messages below the directive element but not in it.
Although I really can't figure out how to pass the form in to the template so it can be accessed by ng-messages.
I've set up a plunker to show you my bare bones setup.
http://plnkr.co/edit/ELx6Fd2eLN4CJjEnzRGM?p=preview
I know I need to require the form with require: '^form', although I'm not sure how to use/access in the template URL.
I've been banging my head for a while so would really appreciate some help! Thanks.
When you require the form directive with require: '^form' you then access that FormController in the link function. You can then simply attach that controller to the directive's scope like so:
link: function(scope, element, attributes, formController) {
scope.form = formController;
}
Then reference it in the template:
<div ng-messages="form.$error">
<div ng-message="required">You did not enter a field</div>
</div>
You could always pass the form to your directive.
javascript
app.directive('selectGov', function (){
return {
restrict: 'E',
templateUrl: 'select.html',
scope: {
text: "=?",
model: "=",
required: "=",
selectItems: "=?",
name: "#?",
form: "="
},
};
});
html
<select-gov model="person.phoneNumberType" text="q.phoneType" required="true" name="phoneType" form="myForm"></select-gov>
Related
I have a checkbox inside ng-form rapped by HTML5 form that I want to exclude so it won't change my form $state($pristine or $dirty).
I have tried using ignoreDirty directive - Angular 1.2: Is it possible to exclude an input on form dirty checking?
and some other solutions and none work for ng-form inside HTML5 form, some example code:
<form name="mainForm" class="col-xs-10 form-validation" novalidate>
<ng-form name="innerForm">
<div>
<span>check my
<span ng-if="vm.utils.mode!=='readonly'">
<input type="checkbox"
ng-model="vm.utils.amalotSecond"
class="secondYearCheckBox">
</span>
</span>
</div>
</ng-form>
<form>
The ignoreDirty directive you provided works fine like in this demo fiddle. The following code example was taken from angular-1-2-is-it-possible-to-exclude-an-input-on-form-dirty-checking. Also try to avoid using nested forms which are not HTML conform. An form element can't have an element form. It will cause problems and errors e.g. the one you are currently facing.
View
<div ng-controller="MyCtrl">
<form name="test">
Watching dirty: <input ng-model="name" /><br />
Ignoring dirty: <select ng-model="gender" ignore-dirty>
<option>male</option>
<option>female</option>
</select><br />
dirty: {{test.$dirty}}
</form>
</div>
AngularJS application
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.name = 'Superhero';
});
myApp.directive('ignoreDirty', [function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$setPristine = function() {};
ctrl.$pristine = false;
}
}
}]);
I want to add custom validation to the angular form.
<div class="form-group" ng-class="{ 'has-error': contactform.inputAmount.$invalid && submitted }">
<label for="inputAmount" class="col-lg-2 control-label">Amount</label>
<div class="col-lg-10">
<textarea ng-model="formData.inputAmount" class="validate[required,custom[comment]] feedback-input" rows="4" id="comment" name="comment" placeholder="Enter Amount to Convert" required></textarea>
</div>
</div>
I want only number or decimal input with inverted commas like
"1"
"123.1"
"123.12221"
How can i add this pattern
Help would be highly appreciated.
Thanks
You can use ng-pattern to validate your textarea.
Checkout here for example.
http://www.java2s.com/Tutorials/AngularJS/AngularJS_Example/Directives/Use_ng_pattern_to_validate.htm
Refer here for dynamic ng-pattern validation Angularjs dynamic ng-pattern validation
Use Directive for custom validations.
First write custom directive:
//Check For FLoat Validation
adminApp.directive('validateFloat', function() {
var FLOAT_REGEXP = /^\-?\d+((\.)\d+)?$/;
return {
require: 'ngModel',
restrict: '',
link: function(scope, elm, attrs, ctrl) {
// only apply the validator if ngModel is present and Angular has added the Float Number validator
ctrl.$validators.validateFloat = function(modelValue) {
return ctrl.$isEmpty(modelValue) || FLOAT_REGEXP.test(modelValue);
};
}
};
});
In directive used Regex for float (or) Decimal to check with ngModel value.
Then use directive in html page.
<input type="text" name="amount" class="form-control" ng-model=test.amount" validate-float required>
<span class="error-container" ng-show="myForm.amount.$dirty && myForm.amount.$invalid">
<span ng-cloak style="color:red" ng-show="myForm.amount.$error.required">Please Enter amount</span>
<span ng-cloak style="color:red" ng-show="!myForm.amount.$error.required&&myForm.amount.$error.validateFloat">Enter valid amount</span>
</span>
In HTML page mention the custom directive "validate-float" as attribute. And for showing error message in ng-Show mention the $error.validateFloat.
For more info about directive and validations: https://docs.angularjs.org/guide/directive,
https://docs.angularjs.org/guide/forms
I'm wondering if it is possible to retrieve the current form in a html template.
To be clear, I actually would like to reuse some form fields this way:
<form name="myForm">
<div ng-include src="'templates/form-field/email.html'">
<div ng-include src="'templates/form-field/password.html'">
</form>
Here is templates/form-field/email.html:
<div>
<label>Email:</label>
<input type="email" name="email" ng-model="data.email" ng-required="true">
</div>
<div ng-show="myForm.email.$error.required && myForm.email.$touched" class="error">Email is required</div>
<div ng-show="myForm.email.$error.email && myForm.email.$touched" class="error">Email is not valid</div>
So this works well and allows me to re-use HTML components including error messages.
However, I have to to give a static name to my form (here "MyForm")
Is there any way to retrieve the current form inside the tags?
I'm quite new with angular so there may even be better ways to achieve the same behavior (i.e. re-use html components / error messages) that I'm not aware of.
I'm interesting in any solution as long as it does not include any 3rd parties.
Maybe using $scope to define the name of the form?
With ng-include it creates a child scope from the parent so the data is only shared one-way, from parent to child. You will need to create a directive instead and set scope to false, or not declare it at all since that is the default, so that the controller and the directive will share the same scope.
Email Directive:
directive('emailTemplate', [function(){
return {
templateUrl: 'templates/form-field/email.html',
link: function(scope, elem, attrs) {
}
};
}]);
Password Directive:
directive('passwordTemplate', [function(){
return {
templateUrl: 'templates/form-field/password.html',
link: function(scope, elem, attrs) {
}
};
}]);
HTML
<form name="myForm">
<email-template></email-template>
<password-template></password-template>
</form>
EDIT
Email Directive:
directive('emailTemplate', [function(){
return {
templateUrl: 'templates/form-field/email.html',
link: function(scope, elem, attrs) {
scope.form = scope[attrs.formName];
}
};
}]);
HTML
<form name="myForm">
<email-template form-name="myForm"></email-template>
<password-template form-name="myForm"></password-template>
</form>
Template
<div>
<label>Email:</label>
<input type="email" name="email" ng-model="data.email" ng-required="true">
</div>
<div ng-show="form.email.$error.required && form.email.$touched" class="error">Email is required</div>
<div ng-show="form.email.$error.email && form.email.$touched" class="error">Email is not valid</div>
Consider the form:
<form class="form" name="myForm" ng-submit="submit()">
<div class="form-group" ng-class="{'has-error': myForm.title.$invalid}">
<label for="title">Title: </label>
<input id="title" name="title" class="form-control" ng-model="title"
required>
<div ng-messages="myForm.title.$dirty && myForm.title.$error" role="alert">
<div ng-message="required" class="alert small with-error-font">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
Title is required!
</div>
</div>
</div>
</form>
I want to achieve the following behaviour:
Validation error message should appear if user started typing and left the field empty (it's not pristine anymore). Otherwise, it shouldn't be visible till user clicks submit.
So I thought it could be done by using sort of 'aspect'/'interceptor' which simply checks if form is valid. If it is, then it should invoke ng-submit function. If not, then it should invoke $setDirty on each field (so that validation errors appear) and simply return.
I want to achieve it by creating ma own directive, like the following:
let validateAndSubmit = function (onValidationSuccessCallback) {
return function () {
// this is where validation logic should happen
onValidationSuccessCallback();
};
};
let ValidatingFormDirective = function () {
return {
restrict: 'E',
transclude: true,
replace: true,
scope: {
name: '#',
postValidationCallback: '&'
},
link: function (scope) {
scope.validateAndSubmit = validateAndSubmit(scope.postValidationCallback);
},
templateUrl: 'app/events/common/forms/validating-form.template.html'
}
};
export default ValidatingFormDirective;
and here's my directive template:
<form name="{{name}}" novalidate ng-submit="validateAndSubmit()" ng-transclude></form>
Problem:
Now if I change form to validation-form in my html, it seems like myForm is not recognized at all, because neither ngMessages block nor ng-class appears.
How can I fix it? Or maybe should I try completely different approach?
I've been trying to develop an AngularJS directive that outputs a labelled form-field.
I'd like to be able to use a tag like the following:
<simpleTextField bind="user.email" label="Email" name="email"
placeholder="Enter email address"></simpleTextField>
This is to produce the following (bootstrap) HTML output:
<div class="form-group">
<label class="col-sm-2 control-label" for="email">Email</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="email"
ng-model="user.email" placeholder="Enter email address">
</div>
</div>
As you can see the attributes include both an attribute that defines a binding and one whose value is to be substituted directly into the template HTML.
I'd like it to be properly encapsulated. In other words, I don't want to have to modify the view's controller in order to accommodate usage of this directive.
None of the examples I've seen satisfy my requirements because (1) they don't substitute the attribute values directly into the template, and/or (2) they rely on the controller of the view in which the directive is being used to be modified.
Please note that I'm new to AngularJS so I may be completely off track here.
I think I have made something that should work.
You can pass in values to directly bind to the template and the directive has no knowledge of the parent's model.
The HTML + directive:
<div ng-controller="MyCtrl">
<label>Parent Scope Email:{{email}}</label></br>
<simple-text-field simple-bind-to="email" simple-label="Email" simple-name="email"
simple-placeholder="Enter email address" simple-dynamic-scope="user.email">
</simple-text-field>
</div>
The directive:
var myApp = angular.module('myApp',[]);
myApp.directive('simpleTextField', function() {
return {
restrict: 'E',
scope: {
simpleBindTo: "=",
simpleLabel: "#simpleLabel",
simpleName: "#simpleName",
simplePlaceholder: "#simplePlaceholder",
},
template: '<div class="form-group">' +
' <label class="col-sm-2 control-label" for="{{simpleName}}">{{simpleLabel}}</label>' +
' <div class="col-sm-10">' +
' <input type="text" class="form-control" name="{{simpleName}}" ' +
' placeholder="{{simplePlaceholder}}" ng-model="simpleBindTo" >' +
' </div>' +
'</div>'
};
});
myApp.controller('MyCtrl', function ($scope) {
$scope.email = '';
});
By using the '=' access modifier, the ng-model can be assigned variable member of the parent scope, without the directive knowing anything about this variable.
Here is a jsfiddle for the above example.