AngularJS Directive for twitter bootstrap form-group

喜你入骨 提交于 2020-01-31 17:45:34

问题


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!


回答1:


UPDATE: this is my latest gist (angular 1.3): https://gist.github.com/lpsBetty/3259e966947809465cbe


OLD solution:

I tried something similiar, maybe this link can help you too: http://kazimanzurrashid.com/posts/create-angularjs-directives-to-remove-duplicate-codes-in-form

This was my solution. I don't know why but I had to use form.$dirty, it was not possible to use input.$dirty.. (and I use angular-translate)

HTML:

<form-group input="form.password">
  <input type="password" class="form-control" placeholder="{{ 'user.password' | translate }}" required
          name="password" ng-model="user.password" />
</form-group>

Directive:

  app.directive('formGroup', function ($parse) {
    return {
      restrict: 'E',
      require: '^form', 
      transclude: true,
      replace: true,
      scope: {
        cssClass: '@class',
        input: '='
      },
      template: '<div class="form-group" ng-class="{\'has-error\':hasError, cssClass:true}">'+
                  '<div ng-transclude></div>' +
                  '<div ng-show="hasError">' +
                    '<span ng-repeat="(key,error) in input.$error" class="help-block"' +
                            'ng-show="input.$error[key]">{{\'form.invalid.\'+key | translate}}</span>' +
                  '</div>' +
                '</div>',
      link: function (scope, element, attrs, ctrl) {
        var form = ctrl;
        var input = attrs.input;

        scope.$parent.$watch(input+'.$invalid', function (hasError) {
          scope.hasError = hasError && form.$dirty;
        });
      }
    };
  });


来源:https://stackoverflow.com/questions/22616898/angularjs-directive-for-twitter-bootstrap-form-group

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!