2012-12-03 20 views
7

ディレクティブを作成するときに2ウェイデータバインディングを維持する方法を理解するのが苦労しています。ここで私はと協力しフィドルいますものです:AngularJsディレクティブ内のデータバインド

http://jsfiddle.net/dkrotts/ksb3j/6/

HTML:

<textarea my-maxlength="20" ng-model="bar"></textarea> 
<h1>{{bar}}</h1> 

指令:

myApp.directive('myMaxlength', ['$compile', function($compile) { 
return { 
    restrict: 'A', 
    scope: {}, 
    link: function (scope, element, attrs, controller) { 
     element = $(element); 

     var counterElement = $compile(angular.element('<span>Characters remaining: {{charsRemaining}}</span>'))(scope); 

     element.after(counterElement); 

     scope.charsRemaining = parseInt(attrs.myMaxlength); 

     scope.onEdit = function() { 
      var maxLength = parseInt(attrs.myMaxlength), 
       currentLength = parseInt(element.val().length); 

      if (currentLength >= maxLength) { 
       element.val(element.val().substr(0, maxLength)); 
       scope.charsRemaining = 0; 
      } else { 
       scope.charsRemaining = maxLength - currentLength; 
      } 

      scope.$apply(scope.charsRemaining); 
     } 

     element.keyup(scope.onEdit) 
      .keydown(scope.onEdit) 
      .focus(scope.onEdit) 
      .live('input paste', scope.onEdit); 
     element.on('ngChange', scope.onEdit); 
    } 
} 
}]); 

私がテキストエリアに入力すると、モデルが更新されていません私はそれが必要なように。私は間違って何をしていますか?

答えて

0

私は完全には分かっていませんが、あなたが嫌い​​なのはフィルタだと思います。このURLを見てみてください。あなたの問題について再考するのは素晴らしいアプローチかもしれません。

http://docs.angularjs.org/api/ng.filter:limitTo

+0

私はそれが私がここで困難を抱えているとは思わない。私の問題はかなり単純です。テキストエリアには、モデルが割り当てられています。 myMaxlengthディレクティブを有効にすると、そのモデルの2ウェイ・バインドが中断されます。 – Dustin

5

あなたが本当にカスタムディレクティブが必要ですか? AngularJSには、ngChangeと組み合わせてngMaxlengthという指示が付いています。次のHTML

<body ng-controller="foo"> 
    <form name="myForm"> 
     <textarea name = "mytextarea" 
        ng-maxlength="20" 
        ng-change="change()" 
        ng-model="bar"></textarea> 
     <span class="error" ng-show="myForm.mytextarea.$error.maxlength"> 
      Too long! 
     </span> 
     <span> {{left}} </span> 
     <h1>{{bar}}</h1> 
    </form>     
</body> 

を持っている場合

たとえば、次に、あなただけの

function foo($scope) { 
    $scope.change = function(){ 
     if($scope.bar){ 
      $scope.left = 20 - $scope.bar.length;    
     }else{ 
      $scope.left = ""; 
     }  
    }; 
    $scope.bar = 'Hello'; 
    $scope.change(); 
} 

お使いのコントローラにこれを必要とすることができます限り、DOMを角度の扱いましょう。

がここに更新jsfiddleです:http://jsfiddle.net/jaimem/ksb3j/7/

+0

組み込みの角度機能を使用したいと思います。しかし、なぜこれによって、文字がテキストエリアに入力されなくなるのでしょうか?それは私がmaxlengthから期待していた動作です。 –

12

まあ、双方向のデータバインディングが動作しない理由は2つある。 まず、あなたは、双方向のローカルスコープのプロパティと親スコープのプロパティ間の結合を作成する必要があります。

scope: { bar: "=ngModel" } 

そうでなければ、孤立スコープを作成している(http://docs.angularjs.org/guide/directiveを参照してください)。

他の理由は(あなただけdom.readyに角度ブートストラップされているため)あなたは親からAPPENDと挿入命令の後に交換しなければならないことです。

element.parent().append(counterElement); 

更新jsfiddle:http://jsfiddle.net/andregoncalves/ksb3j/9/

+0

前もってモデルの名前がわからない場合、どうすればいいですか?また、なぜelement.after()の代わりにelement.parent()。append()を使用する必要がありましたか? – Dustin

+1

モデル名がわからない場合は、宣言的なng-model構文を使用しないでください。コントローラのスコープからモデルを取得してください(ディレクティブでスコープをfalseに設定してください)。 element.parent()。append()に関しては、あなたがdom.readyの起動時にのみ起動しているので、起動時に起動ストラップがまだ発生していない場合は、dom.readyハンドラから削除し、after ()。 –

+0

私は更新されたフィドルをここに持っています:http://jsfiddle.net/dkrotts/WWCzQ/3/。私が今使っている問題は、スコープ変数charsRemainingをディレクティブに分離して、このディレクティブを同じページで複数回使用できるようにすることです。今のように(スコープはfalseです)、charsRemainingは親スコープ全体で共有されており、その特定の変数をディレクティブのみに分離する必要があります。 – Dustin

関連する問題