2

我有一個全局指令,負責從控制器獲取錯誤消息,編譯並顯示它。

如果存在服務器驗證錯誤,例如 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'); 
      } 
     }); 

    }, 
    } 
}). 

回答

4

爲了使用$scope[formName]控制器必須表單元素上。無論是通過直接定義:

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

或者作爲指令:

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

如果這些條件中滿足,那麼你必須定義每個元素的name屬性,你需要訪問:

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

然後可以訪問$setValidity(),相應控制器內,如上面所定義:

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

請注意:爲了讓控制器訪問表單,它必須與表單處於同一元素,或者可能處於子範圍內。

+0

任何方法來制定一個解決方法?,也許一個服務是注入到該指令,並獲取$範圍作爲參數? 這個想法是,這個指令是一個頂級的錯誤欄,它與我在我的應用程序上有很多形式無關 –

+0

也許你可以從適當範圍內的控制器公開表單。但是,你必須格外小心地清理路由變更時的那些引用(通常在控制器超出範圍時)。您也可以使用消息來實現此功能;也許有一些簡單的通用控制器與表單並排(因此可以訪問它)並監聽特定的'$ broadcast'ed消息來觸發'$ setValidity()'。 –

0

嗯,我已經成功在提供了充足的結果的方式來解決這個問題:

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事件中可以通過改變事件或任何其他事件所取代。

相關問題