2

私は、角度1.6.1と材料1.1.1の下で動作する小さな指令を書いています。 シンプルなロック/アンロックボタンのアイコンです。AngularJSのカスタムディレクティブ双方向バインディングが材料のアップグレード後に破損しました

材料を1.1.3(日付選択ツール用)に更新する必要がありましたが、それ以降はディレクティブはもう機能しません。

なぜ材料更新がこれを行うのか分かりません.... 以下のプラカードは動作しますが、材料バージョンを1.1.2に変更すると動作しなくなります。

http://plnkr.co/edit/ZamxN3WTXaOl5cTv4aWI?p=info

のindex.html:

<html lang="en" > 
<head> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.3/angular-material.css"> 
    <link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons"> 
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script> 
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script> 
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-aria.js"></script> 

    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.1/angular-material.js"></script> 
    <!-- <script src="//cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.1/angular-material.js"></script> --> 

    <script src="script.js"></script> 

</head> 
<body ng-app="app" ng-controller="controller as ctrl"> 
    <ju-lock ng-model="ctrl.lock"></ju-lock>|{{ctrl.lock}}| 
</body> 
</html> 

script.js:

angular 
    .module('app', ['ngMaterial']) 
    .directive('juLock', function(){ 
     return { 
      restrict: 'E', 
      scope: { 
       bindModel: '=ngModel' 
      }, 
      template: 
       '<md-button class="md-icon-button">'+ 
       '<md-icon class="material-icons">lock_open</md-icon>'+ 
       '</md-button>|{{bindModel}}', 
      link: function(scope, element, attributes){ 
       element.on('click', function (ev) { 
        scope.bindModel = !scope.bindModel; 
       }); 
       scope.$watch('bindModel', function(){ 
        angular.element(element[0].querySelector('.material-icons')).text(scope.bindModel ? 'lock' : 'lock_open'); 
       }); 
      } 
     }; 
    }) 
    .controller('controller', function(){ 
     var vm = this; 
     vm.lock=true; 
    }); 

私は、スタックのコミュニティを尋ねる前に、誰もがいくつかの洞察力を持っていない可能性ができるだけ多くを調査しましたこれに?

+0

避ける:それはng-showng-hideディレクティブで行うことができます。その場合は、分離スコープの双方向バインディングを使用しないでください。その属性がインスタンス化する[ngModelController API](https://docs.angularjs.org/api/ng/type/ngModel.NgModelController)を使用します。 – georgeawg

答えて

1

バージョン間の正確な問題についてはわかりませんが、これはfiddleにチェックしてください。このコードは両方のバージョンで動作します。

ng-clickelement.on()に依存するのではなく、angularJsのもので、jQueryを注入した場合とそうでない場合があります。プラスこの方法は、私がやった唯一の変化は、私はまた、あなたの時計にDOM検査を取り出し、と私はより多くの角度スタイル

2

避けでそれをやったあなたのディレクティブで

.directive('juLock', function(){ 
     return { 
      restrict: 'E', 
      scope: { 
       bindModel: '=ngModel' 
      }, 
      template: 
       '<md-button ng-click="bindModel = !bindModel" class="md-icon-button">'+ 
        '<md-icon class="material-icons">{{lock_text}}</md-icon>'+ 
       '</md-button>|{{bindModel}}', 
      link: function(scope, element, attributes){ 
       scope.lock_text = ''; 
       scope.$watch('bindModel', function(){ 
        scope.lock_text = scope.bindModel ? 'lock' : 'lock_open'; 
       }); 
      } 
     }; 
    }) 

より宣言でありますカスタムディレクティブの属性としてng-modelを使用します。その場合は、分離スコープの双方向バインディングを使用しないでください。その属性がインスタンス化するngModelController APIを使用します。

主な問題は、scope().$apply()とスコープに変更のAngularJSフレームワークに通知するjqLite click handler必要である:

element.on('click', function (ev) { 
    scope.bindModel = !scope.bindModel; 
    //USE $apply 
    scope.$apply(); 
}); 

角度は、独自のイベント処理ループを提供することにより、通常のJavaScriptの流れを変更します。これにより、JavaScriptが古典的なAngular実行コンテキストに分割されます。 Angular実行コンテキストで適用される操作のみが、Angularデータバインディング、例外処理、プロパティ監視などから利益を得ます。$apply()を使用して、JavaScriptからAngular実行コンテキストを入力します。

ほとんどの場所(コントローラ、サービス)で、$applyはイベントを処理しているディレクティブによって既に呼び出されています。 $applyへの明示的な呼び出しは、カスタムイベントコールバックを実装する場合、またはサードパーティのライブラリコールバックを使用する場合にのみ必要なです。代わりにロックを変更すると、アイコンのロックを解除するためにDOMを操作するのも

— AngularJS Developer Guide v1.1 - Concepts - Runtime

DEMO on PLNKR


。カスタムディレクティブの属性として `NG-model`を使用して

app.directive('juLock', function(){ 
    return { 
     restrict: 'E', 
     scope: { 
      bindModel: '=myModel' 
     }, 
     template: 
      '<md-button class="md-icon-button">'+ 
      '<md-icon ng-show="bindModel" class="material-icons">lock</md-icon>'+ 
      '<md-icon ng-hide="bindModel" class="material-icons">lock_open</md-icon>'+ 
      '</md-button>|{{bindModel}}', 
     link: function(scope, element, attributes){ 
      element.on('click', function (ev) { 
       scope.bindModel = !scope.bindModel; 
       //USE $apply 
       scope.$apply(); 
      }); 
      /* 
      scope.$watch('bindModel', function(){ 
       angular.element(element[0].querySelector('.material-icons')).text(scope.bindModel ? 'lock' : 'lock_open'); 
      }); 
      */ 
     } 
    }; 
}) 
関連する問題