0

我有一個AngularJS指令,我正在使用延遲表單字段驗證,既在模糊上也在空閒(一段時間內沒有輸入)上進行實驗。我有兩種方法聯繫起來;一種是在實際輸入字段上添加一個類,另一種是在範圍上設置一個狀態變量。設置類可以用於設置字段樣式,但我更關心樣式(ng顯示)幫助消息,它位於不相關的元素上。此外,類可以添加ng類,所以我想要的方法似乎應該是一個狀態變量屬性檢查。AngularJS指令,公開視圖狀態

我的問題:

  1. 有沒有一種方法,我可以很容易地從指令露出一個isActive狀態,使得來電者沒​​有在外部屬性通過充當中介?這實際上不是外部狀態,它是所有視圖導向的,我只是想從HTML中徹底訪問它。
  2. $ error,$ invalid等是如何附加到元素上並解析的?我可以在用戶代碼中構建相同的功能嗎?即element.state.active?

<form name="f"> 
     <div class="form-group" ng-class="{'has-error': f.e.$invalid}"> 
      <label>Enter Email Address</label> 
      <input type="email" class="form-control" name="e" ng-model="user.email" required autofocus active="1500" is-active="state.active"/> 
      <p class="help-block" ng-show="!state.active && f.e.$error.required">email is required</p> 
      <p class="help-block" ng-show="!state.active && f.e.$error.email">enter a valid email address</p> 
      <p class="help-block" ng-show="state.active">typing...</p> 
      <p class="help-block" ng-show="!state.active && f.$valid">ok!</p> 

     </div> 
    </form> 

和相關的指令......

app.directive('active', ['$parse', function ($parse) { 
     var tid; 
     return { 
      restrict: 'A', 
      require: '?ngModel', 
      scope: 
      { 
       isActive: "=", 
       ngModel: "=" 
      }, 

      link: function (scope, elem, attrs, ctrl) { 
       elem.bind('blur', function() 
       { 
        scope.isActive = false; 
        elem.removeClass("ng-active"); 
       }); 
       var timeout = attrs.active || 2000; 
       ctrl.$parsers.unshift(function(value) 
       { 
        scope.isActive = true; 
        console.log("adding class"); 
        elem.addClass("ng-active"); 
        if (tid) clearTimeout(tid); 

        tid = setTimeout(function() 
        { 
         console.log("timeout elapsed, removing class"); 
         scope.$apply(function(){ 
         scope.isActive = false; 
         }); 
         elem.removeClass("ng-active") 


        }, timeout); 
        return value; 
       }) 


      } 
     }; 
    }]); 

//myApp.directive('myDirective', function() {}); 
//myApp.factory('myService', function() {}); 

function TestCtrl($scope) 
{ 
    $scope.testName = "Validation Test"; 
    $scope.user = { 
     email: '[email protected]' 
    }; 
    $scope.state = { 
     active: false 
    }; 

} 

這裏是​​

基本上,它的工作原理,但我不喜歡,我必須通過在每個輸入字段的外部屬性,我不喜歡驗證檢查時的不對稱性。有沒有更好的方法來做到這一點?

回答

1

你可以嘗試:ngModelController.$setValidity

app.directive('active', ['$parse', function ($parse) { 
     var tid; 
     return { 
      restrict: 'A', 
      require: '?ngModel', 
      scope: 
      { 
       ngModel: "=" 
      }, 

      link: function (scope, elem, attrs, ctrl) { 
       elem.bind('blur', function() 
       { 
        scope.$apply(function(){ 
         ctrl.$setValidity("active",true); 
        }); 
       }); 
       var timeout = attrs.active || 2000; 
       ctrl.$parsers.unshift(function(value) 
       { 
        ctrl.$setValidity("active",false); 
        console.log("adding class"); 

        if (tid) clearTimeout(tid); 

        tid = setTimeout(function() 
        { 
         ctrl.$setValidity("active",false); 
        }, timeout); 
        return value; 
       }) 


      } 
     }; 
    }]); 

1)設置活動是這樣的:ctrl.$setValidity("active",true);

2)像這樣訪問html:f.e.$error.active

3)注意,當我們利用此功能:ctrl.$setValidity("active",true);,意味着不能active沒有錯誤=>f.e.$error.active == true(一種扭轉當前的邏輯)

DEMO

另一種解決方案是隻添加屬性直接到你的ngModelController:ctrl.active = false;並在html中訪問它,如下所示:f.e.active。但是這個解決方案並不是很好的IMO,因爲它可能會在角度決定創建一個具有相同名稱的新屬性時與未來的角度版本相沖突。

DEMO

+0

我想你的第一個解決方案,但由於 「主動」 實際上只是一個信息位的樣式,而不是一個錯誤,把任何東西無效形式將無法正常工作。 你的第二個答案是我要找的;我可以發誓,我嘗試過,不知道我拙劣的。我瞭解名稱衝突的可能性,但似乎合理的是,應該有一種方法讓用戶以與Angular相同的方式擴展元素。我會在它上面添加一個唯一的前綴。謝謝! –

+0

@Jolly Roger:不需要發誓。祝你今天愉快。我很高興它有幫助。 –

1

要建立在@Khanh TO的(第二)的答案,我已經更新了小提琴我原來的一個小更緊密地匹配和刪除一些錯別字。然後,我使用暴露的狀態來使用ng-class適當地設置幫助文本和輸入字段的樣式。

Go forth and fiddle!

留給後人,HTML中的相關內容:

<form name="f"> 
    <div class="form-group" ng-class="{'has-error': !f.e.active && f.e.$invalid}"> 
     <label>Enter Email Address</label> 
     <input type="email" ng-class="{'active' : f.e.active}" class="form-control" name="e" ng-model="user.email" required autofocus active="1500" /> 
     <p class="help-block" ng-show="!f.e.active && f.e.$error.required">email is required</p> 
     <p class="help-block" ng-show="!f.e.active && f.e.$error.email">enter a valid email address</p> 
     <p class="help-block" ng-show="f.e.active">typing...</p> 
     <p class="help-block" ng-show="!f.e.active && f.$valid">ok!</p> 

    </div> 
</form> 

和JS:

app.directive('active', ['$parse', function ($parse) { 
     var tid; 
     return { 
      restrict: 'A', 
      require: '?ngModel', 

      // warning - this adds an "active" property to ctrl; consider prefixing to avoid future collisions 
      link: function (scope, elem, attrs, ctrl) { 
       elem.bind('blur', function() 
       { 
        ctrl.active = false; 
       }); 
       var timeout = attrs.active || 2000; 
       ctrl.$parsers.unshift(function(value) 
       { 
        ctrl.active = true; 
        if (tid) clearTimeout(tid); 

        tid = setTimeout(function() 
        { 
         scope.$apply(function(){ 
          ctrl.active = false; 
         }); 

        }, timeout); 
        return value; 
       }) 


      } 
     }; 
    }]);