【问题标题】:Using $setValidity on an element outside of the current scope在当前范围之外的元素上使用 $setValidity
【发布时间】:2016-01-20 02:52:50
【问题描述】:

我有一个全局指令,负责从控制器获取错误消息,编译并显示它。

如果出现服务器验证错误,例如 This email already exists,我想关注这个元素,并将它的有效性设置为 false,例如$setValidity(false).

该指令不是表单,也不包含表单。

你有什么建议(已经尝试了所有被注释掉的东西)

directive('messageCompile', function ( $compile, $window, $rootScope ) {
  return {
    restrict: 'A',
    scope: true,
    link: function ( scope, element, attrs ) {
      var el;

      attrs.$observe( 'template', function ( tpl ) {
        if ( angular.isDefined( tpl ) ) {
          // compile the provided template against the current scope
          el = $compile( tpl )( scope );
          // stupid way of emptying the element
          element.html("");

          // add the template content
          element.append( el );
        }
      });
      attrs.$observe('focus', function(val){
        if ( angular.isDefined( val )  && Boolean(val)) {
          var el = angular.element('[name="' + attrs.focus + '"]');
          var form = el.parents().find('form');
          var formName = form.attr('name');
           el.focus();
          // scope[formName].$setValidity(val, false);       
          // el.scope().$setValidity(false);
          // scope[formName][val].$setValidity(false);
          //$rootScope.scope[formName][val].$setValidity(false);
          //$rootScope.scope[formName].$setValidity(val, false);
        }
      });
        var windowEl = angular.element($window);
        windowEl.on('scroll', function() {
          if(window.scrollY > 46){
            element.parent().parent().addClass('stayTop');

            // alert('here');
          }  
          else{
            // alert('here2');
            element.parent().parent().removeClass('stayTop');
          }
        });

    },
  }
}).

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope angularjs-forms


    【解决方案1】:

    为了使用$scope[formName],控制器必须在表单元素上。通过直接定义:

    <form name="theForm" ng-controller="TheCtrl">
    

    或作为指令:

    directive("myDirective", function() {
        return {
            template: "<form name='theForm'>...</form>",
            controller: ["$scope", function($scope) {
                ...
            }],
            ...
        };
    });
    

    如果满足其中一个条件,则必须为需要访问的每个元素定义名称属性:

    <form name="theForm" ...>
        <input name="theInput" ...>
    

    然后你可以访问$setValidity(),在相应的控制器内部,如上定义:

    $scope.theForm.theInput.$setValidity(false);
    

    再次记住:为了让控制器访问表单,它必须与表单位于同一元素,或者可能位于子范围内。

    【讨论】:

    • 有什么办法可以解决?,也许是注入指令并获取 $scope 作为参数的服务?认为这个指令是一个顶级错误栏,它与我的应用程序中的众多表单无关
    • 也许您可以从适当范围内的控制器公开表单。但是,您必须格外小心地清理路由更改时的这些引用(通常是当控制器超出范围时)。您也可以通过消息实现此功能;也许一些简单的通用控制器与表单并排放置(因此可以访问它)并侦听特定的$broadcasted 消息以触发$setValidity()
    【解决方案2】:

    好吧,我已经设法解决了这个问题,并给出了足够的结果:

    attrs.$observe('focus', function(val){
        if (angular.isDefined(val)  && Boolean(val)) {
            var el = angular.element('[name="' + attrs.focus + '"]');
            var form = el.parents().find('form');
            var formName = form.attr('name');
            el.focus();
            el.removeClass('ng-valid').addClass('ng-invalid');
            el.bind('keyup', function(){
                el.removeClass('ng-invalid');
                el.unbind('keyup');
            });
        }
    });
    

    当然,keyup 事件可以替换为 change 事件或任何其他事件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-12-09
      • 1970-01-01
      • 1970-01-01
      • 2012-05-06
      • 2014-05-26
      相关资源
      最近更新 更多