Liaison de données dans la directive AngularJs

J'ai du mal à trouver comment m'assurer de maintenir la liaison bidirectionnelle de données lorsque je crée des directives. Voici ce que je travaille et le violon:

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

HTML:

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

Directif:

 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); } } }]); 

Comme je tape dans la zone de texte, le modèle ne se met pas à jour comme j'en ai besoin. Qu'est-ce que je fais mal?

Eh bien, il existe deux raisons pour lesquelles la liaison bidirectionnelle ne fonctionne pas. Tout d'abord, vous devez créer une liaison bidirectionnelle entre une propriété de portée locale et la propriété de portée parentale:

 scope: { bar: "=ngModel" } 

Sinon, vous créez une portée isolée (voir http://docs.angularjs.org/guide/directive ).

L'autre raison est que vous devez remplacer l'instruction d'insertion après ajout d'une annexe du parent (car vous n'êtes que du bootstrack angular sur dom.ready):

 element.parent().append(counterElement); 

Mise à jour jsfiddle: http://jsfiddle.net/andregoncalves/ksb3j/9/

Avez-vous vraiment besoin d'une directive personnalisée? AngularJS livré avec une directive ngMaxlength combinée à ngChange peut vous aider.

Par exemple, si vous avez le HTML suivant

 <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> 

Ensuite, vous avez besoin de cela dans votre contrôleur

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

Laissez les angulaires manipuler le dom autant que possible.

Voici le jsfiddle mis à jour: http://jsfiddle.net/jaimem/ksb3j/7/

Je ne suis pas tout à fait sûr, mais je pense que ce que vous voulez être un filtre, regardez cette URL, peut-être que c'est une excellente approche pour repenser votre problème.

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