I've been playing with angular lately, so far so good, but im struggling with directives.
I'm trying to create a directive that generates the html mark up for a standard bootstrap form group with its corresponding validation messages.
So basically I'm trying to convert this:
<form-group label="Password">
<input type="password" data-ng-model="vm.password" name="password" id="password" class="form-control form-control-validate"
required data-ng-minlength="6"
data-required-error="Password is required" data-minlength-error="Your password must have at least 6 characters" />
</form-group>
into this:
<div class="form-group" data-ng-class="{'has-error': invalid}">
<label for="password" class="col-md-2 control-label">Password</label>
<div class="col-md-10">
<input data-ng-model="vm.password" type="password" id="password" name="password" class="form-control"
required data-ng-minlength="6"/>
<div data-ng-show="changePasswordForm.$dirty && changePasswordForm.oldPassword.$invalid">
<label data-ng-show="changePasswordForm.oldPassword.$error.required" class="label label-danger">
Password is required
<br />
</label>
<label data-ng-show="changePasswordForm.oldPassword.$error.minlength" class="label label-danger">
Your password must have at least 6 characters
</label>
</div>
</div>
</div>
So far this is what I have:
app.directive('formGroup', function () {
return {
templateUrl: 'app/directives/formGroup.html',
restrict: 'E',
replace: true,
transclude: true,
require: "^form",
scope: {
label: "@",
},
link: function (scope, element, attrs, formController) {
var input = element.find(":input");
var id = input.attr("id");
scope.for = id;
var inputName = input.attr("name");
// Build the scope expression that contains the validation status.
// e.g. "form.example.$invalid"
var inputInvalid = [formController.$name, inputName, "$invalid"].join(".");
scope.$parent.$watch(inputInvalid, function (invalid) {
scope.invalid = invalid;
});
}
};
});
formGroup.html:
<div class="form-group" ng-class="{ 'has-error': invalid }">
<label class="col-md-2 control-label" for="{{for}}">{{label}}</label>
<div class="col-md-10">
<div data-ng-transclude=""></div>
</div>
</div>
This sets correctly the bootstrap class "has-error" to the form-group if the input is invalid.
Now I want to add validation messages, and I couldn't find a way that works. This is what I have:
app.directive('formControlValidate', function () {
return {
templateUrl: "app/directives/formControlValidate.html",
restrict: 'C',
require: ["^form", "ngModel"],
scope: { },
transclude: true,
//replace: true,
link: function (scope, element, attrs, controls) {
var form = controls[0];
var inputName = attrs.name;
var inputErrors = [form.$name, inputName, "$error"].join(".");
scope.$parent.$watch(inputErrors, function (newValue) {
if (newValue) {
scope.errors = [];
angular.forEach(newValue, function (value, key) {
var error = attrs[key + 'Error'];
if (value && error) {
scope.errors.push(error);
}
});
}
}, true);
}
};
formControlValidate.html:
<div class="controls" ng-transclude></div>
<div data-ng-repeat="error in errors">
<div class="label label-danger">
{{error}}
</div>
</div>
But this doesn't work. I'm randomly changing parameters in both directives but can't figure out what how to make it work.
Any ideas or improvements would be greatly appreciated.
Thanks!