Как отобразить angular ошибку проверки формы внутри angular bootstrap popover?

Я новичок в angular js. Я хочу показать ошибку формы в angular bootstrap popover в правой части элемента. Я попытался создать директиву, и я получил элемент, когда он меняет классы. Но я не знаю, как двигаться дальше.

(function(angular) {
  'use strict';
var app=angular.module('formExample', [])
  .controller('ExampleController', ['$scope', function($scope) {
    $scope.master = {};

    $scope.update = function(user) {
      $scope.master = angular.copy(user);
    };

    $scope.reset = function(form) {
      if (form) {
        form.$setPristine();
        form.$setUntouched();
      }
      $scope.user = angular.copy($scope.master);
    };

    $scope.reset();
  }]);
app.directive("alert", function(){
    return {
        restrict: 'C',
        priority: -1000,
        link: function(scope, ele, attrs, ctrl){
          scope.$watch(function() {console.log(ele.attr('class')); })
          if (ctrl) {
            console.log("applying custom behaviour to input: ", ele.attr('id'));
            // ... awesomeness here
          }
        }
    };
});
})(window.angular);

Я просто хочу показать сообщение об ошибке

  • , когда пользователь нажимает кнопку сохранения (все сообщения об ошибках формы)
  • размытие элемента (только для элемента, который потерял фокус)

Вот мой plnkr, который я пытался получить.

Обновить

Как-то я отобразил кнопку angular bootstrap popover и close, которая закрывает popover.

У меня есть две проблемы в текущем plunker.

  • Я хочу отобразить сообщение об ошибке внутри моего шаблона popover соответствующий элементу, где он открывается. мне нужно это шаблон, потому что мне нужна кнопка закрытия.
  • Как только я закрыл popover, если поле пустое и пользователь нажимает отправить popover не открывается в следующий раз. Я хочу показать ошибку сообщение каждый раз при отправке.

Ответы

Ответ 1

Как разместить свой шаблон следующим образом:

<script type="text/ng-template" id="myPopoverTemplate.html">
  <div class="gmePopover">
    <div class="popover-header">
      <button type="button" class="close" popover-toggle><span aria-hidden="true">&times;</span></button>
    </div>
    <div class="popover-content">
        somecontent
    </div>
  </div>
</script>

Рабочий Plunker здесь.

UPDATE:

Вы можете использовать angularjs foreach, чтобы перебирать все ошибки в вашей форме, а затем оттуда вы можете показать базу popover для своего элемента. Что-то вроде этого: рабочий плункер

<script type="text/javascript">
  var app=angular.module('testApp', ['ngAnimate', 'ngSanitize'], function($httpProvider) {});
  app.controller("PopoverDemoCtrl", function($scope, $http, $window) {
    $scope.validate = function() {
        var _popover;
        var error = $scope.testForm.$error;
        angular.forEach(error.required, function(field){
            var message = 'This field (' + field.$name + ') is required';
            _popover = $('#' + field.$name).popover({
              trigger: 'manual',
              title: '<span class="text-info"><strong>title</strong></span>'+
            '<button type="button" id="close" class="close" onclick="$(&quot;#' + field.$name + '&quot;).popover(&quot;hide&quot;);">&times;</button>',
              content: message,
              html: true
            });

            return $('#' + field.$name).popover("show")
        });
    };
  });
</script>

Ответ 2

Вы можете создать директиву, которая перехватывает метод $setSubmitted FormController.

Подробнее о методе здесь

Пожалуйста, найдите рабочий пример здесь

Если эта директива перехватывает метод $setSubmitted, мы можем уведомить другую директиву о том, чтобы показать ошибки проверки в bootstrap popover.

Я работаю при следующих предположениях (не стесняйтесь исправлять меня):

  • вы будете использовать тег формы
  • в теге формы вы получите ng-submit="nameOfForm.$valid && vm.onSubmit()"

Решение работает с двумя директивами:

submitNotify и popoverValidation

submitNotify уведомляет popoverValidation, когда форма отправлена, директива popoverValidation затем показывает ошибки формы, если они есть.

Директива 1: submitNotify

directive('submitNotify', function () {
    return {
        restrict: 'A',
        require: 'form',
        controller: function SubmitNotify() { },
        link: function (scope, element, attrs, form) {                
            var $setSubmitted = form.$setSubmitted;
            form.$setSubmitted = function () {
                $setSubmitted.bind(form)();
                scope.$broadcast('onSubmitNotify');
            };
        }
    };
})

Пояснение:

  • Может использоваться только как директива атрибута
  • Требуется тег form или ngForm

Функция связи:

Функция ссылки заменяет функцию $setSubmitted функцией обратного вызова. Функция обратного вызова уведомляет директиву popoverValidation, что форма была отправлена.

Директива 2: popoverValidation

directive('popoverValidation', [function () {
    return {
        restrict: 'A',
        require: ['ngModel', '^submitNotify'],
        link: function (scope, element, attrs, require) {
            scope.$on('onSubmitNotify', function () {
                var ngModel = require[0];
                if (!ngModel.$valid) {
                    showPopover(ngModel.$error);
                }
            });

            function showPopover( $error) {
                var options = {
                    content: getValidationErrorsHtml($error),
                    html: true,
                    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content popover-content-errors"></div></div>',
                    title: '<span class="text-info"><strong>Error</strong></span><button type="button" data-dismiss="popover" class="close">&times;</button>',
                    trigger: 'manual'
                }
                $(element).popover(options);
                $(element).on('shown.bs.popover', hidePopover);
                $(element).popover('show');                    
            }

            function hidePopover() {
                $(this).next('.popover').find('button[data-dismiss="popover"]').click(function (e) {
                    $(element).popover('hide');
                });
            }

            function getValidationErrorsHtml($error) {
                var errors = [];

                if ($error.required) {
                    errors.push(requiredErrorMessage());
                }

                if ($error.email) {
                    errors.push(invalidEmailAddress());
                }

                var errorHtml = '<ul class="list-group">';

                for (var i = 0; i < errors.length; i++) {
                    errorHtml += '<li class="list-group-item">' + errors[i] + '</li>';
                }

                errorHtml += '</ul>';

                return errorHtml;
            }

            function requiredErrorMessage() {
                return 'This field is required';
            }

            function invalidEmailAddress() {
                return 'Please enter a valid email address';
            }
        }
    };
}]);

Пояснение:

  • Может использоваться только как директива атрибута
  • Требуется тег submitNotify в родительском form

Функция связи:

  • Директива popoverValidation получает уведомление о том, что форма отправлена ​​
  • Проверяет, действительно ли свойство привязано ng-model
  • Если недействительно, отображается popover.

Завершить HTML:

<form name="myForm" ng-controller="MyFormController as vm" ng-submit="myForm.$valid && vm.onSubmit()" submit-notify="" novalidate>
    <div class="panel panel-primary">
        <div class="panel-heading">Form Validation with Popovers</div>
        <div class="panel-body">
            <div class="form-group">
                <label>First name</label>
                <input type="text" name="firstName" class="form-control" required ng-model="person.firstName" popover-validation="" />
            </div>
            <div class="form-group">
                <label>Surname</label>
                <input type="text" name="surname" class="form-control" required ng-model="person.surname" popover-validation="" />
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="email" name="email" class="form-control" ng-model="person.email" popover-validation="" />
            </div>
        </div>
        <div class="panel-footer">
            <button type="submit" class="btn btn-success">Submit</button>
        </div>
    </div>
</form>

Некоторые CSS:

<style type="text/css">
    .popover-content-errors {
        padding:0px;
    }

    .popover-content-errors .list-group {
        margin-bottom:0px
    }

    .popover-content-errors .list-group-item {
        border-left:none;
        white-space:nowrap;
    }

    .popover-content-errors .list-group-item:first-child {
        border-top:none;
    }

    .popover-content-errors .list-group-item:last-child {
        border-bottom:none;
    }
</style>

MyFormController

controller('MyFormController', ['$scope', function ($scope) {
    var self = this;
    $scope.person = {
        email:'john.doe.com'
    }
    self.onSubmit = function () {   
        console.log('MyFormController.onSubmit');
    };
}]);