How to make an input field into a reusable field? - angularjs

I have this input with lots of directives on it:
<input class="form-control"
mobile-number
limit-characters
number-only
dir="ltr"
ng-class="{'error-form-control': vm.form.step2.phoneNumber.$invalid && (vm.form.step2.phoneNumber.$dirty || vm.form.step2.phoneNumber.$touched)}"
required
ng-model="vm.formData.phoneNumber"
name="phoneNumber"
type="text">
How can I make it into a reusable directive like so:
<phone-number ng-model="vm.formData.phoneNumber"></phone-number>
and how can I use angular form validation with this directive?

I guees it will look like this
app.directive('phoneNumber', function(){
return {
scope: {
ngModel: '='
classValidation: '=',
inputName: '#'
},
template: ' <input class="form-control" mobile-number limit-characters number-only dir="ltr" ng-class="classValidation" required ng-model="ngModel" name="{{inputName}}" type="text">',
link: function(scope, elem, attr, ctrl) {
}
}
})
HTML
<phone-number ng-model="vm.formData.phoneNumber" input-name="phoneNumber" class-validation="{'error-form-control': vm.form.step2.phoneNumber.$invalid && (vm.form.step2.phoneNumber.$dirty || vm.form.step2.phoneNumber.$touched)}"></phone-number>

Related

AngularJs Directive not found

Here im trying to Binding directive but why i'm getting error during the Binding
<input type="text" class="form-control" ng-model="User.Password" name="psw" />
<input type="text" class="form-control" ng-model="User.conPassword" name="cpsw"
data-apple-psw="User.Password" required />
crl.Js
app.directive('applePsw', function () {
return {
require: " ngModel",
scope: {
//passwordVerify: "="
applePsw: "="
},
link: function (scope, element, attr, ctrl) {

ng-messages not showing in directive

I'm trying to re-use code as much as I can so I'm wrapping ng-messages in a directive. However, the messages are not shown..
<form name="elementForm" novalidate>
<md-input-container>
<label>Category</label>
<input ng-required="true" ng-model="item.category" name="category" type="text">
<administration-input-validation control="category" formname="elementForm"></administration-input-validation>
</md-input-container>
</form>
Directive:
angular.module('app.analytics')
.directive('administrationInputValidation', function () {
return {
template:
'<div ng-messages>' +
'<div ng-message="required">This is required</div>' +
'</div>',
restrict: 'E',
replace: true,
require: '^form',
scope: {
control: '=',
formname: '='
},
link: function(scope, element, attrs) {
var formStr = attrs.formname + "." + attrs.control;
element.attr("ng-messages", formStr + "." + "$error");
}
};
});
I also tried hardcoding but it's still not showing
<div ng-messages="elementForm.category.$error">
UPDATE
Binding works now, but it's not showing the messages

Access validation error message custom directive

<form-input label="Product Name" required name="name" model="ProdEdit.product.title"></form-input>
App.directive('formInput', function($timeout) {
var template = '<div class="form-group">'+
'<label for="{{id}}">{{label}}</label>'+
'<input type="text" required name="{{name}}" class="form-control" ng-model="model" id="{{id}}" placeholder="Enter {{label}}">'+
'<div ng-messages="myForm.name.$error" class="text-danger"></div>'+
'<span ng-message="required" >This is mandatory</span>'+
'</div>';
return {
restrict: 'E',
require: "^ngMessages",
template: template,
scope: {
label: "#",
model: "=",
name: "#",
required : "&"
},
replace: true
};
})
I created a form input directive like above. Now I want to show error message in span. Kindly help me out.

angular 1.4 directive toggle view

I want to show two different inputs depending on a toggle attribute.
No I have the problem that I should define each attribute/property of the input in my directive, but the binding doesn't work.
Directive:
angular.module('directive')
.directive('inputBlock', function () {
return {
restrict: 'AEC',
replace: true,
scope: {
model: '=',
modernStyle:'=',
name:'=',
type:'=',
label:'='
},
link: function (scope, elem, attrs, ctrl) {},
templateUrl: 'views/templates/inputBlockTemplate.html'
};
});
Template:
<div>
<div ng-if="!modernStyle">
<label>{{label}}</label>
<input ng-model="model" name="{{name}}" type="{{type}}"/>
</div>
<md-input-container ng-if="modernStyle">
<label>{{label}}</label>
<input ng-model="model" name="{{name}}" type=" {{type}}"/>
</md-input-container>
</div>
Usage:
<input-block model="name" label="'firstname'" modern-style="true" name="'firstname'" type="'text'">
</input-block>
Is it possible to do something like a toggle in directives?
Furthermore is it possible to redirect the bindings to directives?
ng-if creates a new child scope, try change by ng-show/ng-hide
Understanding Scopes
Other considerations:
As you use name,label and type as text inside your directive is not necesary that it will be binding, I recomend use # instead of =, or access it directly from the attrs link argument.
The scope.model could be set as ngModel to use the default angular directive.
Javascript:
angular.module("directive").directive("inputBlock", function () {
return {
restrict: "AEC",
replace: true,
scope: {
ngModel: "=",
modernStyle:"#",
//name:"#",
//type:"#",
//label:"#"
},
link: function (scope, elem, attrs, ctrl) {
scope.type=attrs.type;
scope.name=attrs.name;
scope.label=attrs.label;
},
templateUrl: "views/templates/inputBlockTemplate.html"
};
});
Template:
<div>
<div ng-show="!scope.modernStyle">
<label>{{scope.label}}</label>
<input ng-model="scope.model" name="{{scope.name}}" type="{{scope.type}}"/>
</div>
<md-input-container ng-show="scope.modernStyle">
<label>{{scope.label}}</label>
<input ng-model="scope.model" name="{{scope.name}}" type={{scope.type}}"/>
</md-input-container>
</div>
Usage:
<input-block ng-model="name" label="firstname" modern-style="true" name="firstname" type="text">
</input-block>

Directly access form element from form.FormController?

I'm working on several components (directives) to aid in form validation. I'd like the components to be aware of the related input element's state (such as required). For example...
Markup:
<form name="editUser">
<control-label input="editUser.name">Name</control-label>
<input type="text" name="name" ng-model="user.name" required/>
</form>
Directive:
app.directive("controlLabel", function() {
return {
restrict: "E",
replace: true,
transclude: true,
scope: {
input: "=input"
},
template:
'<label class="control-label">'+
'<span ng-transclude>{{label}}</span>'+
'<span ng-if="input.required"> (required!)</span>'+ // doesn't work?
'</label>'
};
});
Output:
<form name="editUser">
<label>
<span>Name</span>
<span>(required!)</span>
</label>
<input type="text" name="name" ng-model="user.name" required/>
</form>
The source for form.FormController leaves me to believe this isn't possible. Is there any way to at least get access to the attrs on the element? I thought about using a decorator, but so far I haven't been able to figure out how that would be done.
You should use input.$validators.required instead of input.required as:
myApp.directive("controlLabel", function() {
return {
restrict: "E",
replace: true,
transclude: true,
scope: {
input: "=input"
},
template:
'<label class="control-label">'+
'<span ng-transclude>{{label}}</span>'+
'<span ng-if="input.$validators.required"> (required!)</span>'+
'</label>'
};
});
Working Demo
First, there's an error in your code. If you're using transclude, you will have to declare it in your directive, or you will get an error.
As for your problem, within a directive, you can access DOM element. And for this particular use case, you can even get by without creating isolated scope or extra attribute at all:
app.directive("controlLabel", function() {
return {
restrict: "E",
replace: true,
scope: true, // if needed, can also use empty isolated scope { }
transclude: true, // must declare this
template:
'<label class="control-label">' +
'<span ng-transclude>{{label}}</span>' +
'<span ng-if="show"> (required!)</span>' +
'</label>',
link: function(scope, jqElem, attrs) {
// check if next sibling of this directive is required
scope.show = (jqElem.next().attr("required") === 'required');
}
};
});
Now your control label is really minimal and DRY, and the logic is well encapsulated within a directive. The only requirement is that your directive target must be the next sibling of the label:
<control-label>Name</control-label>
<input type="text" name="name" ng-model="user.name" required/>
Of course, if needed, you can use your jquery-fu to change the link function to suit your other requirements.

Resources