2012-12-03 15 views
7

Sto riscontrando delle difficoltà nel capire come mantenere il binding dei dati a 2 vie quando creo le direttive. Ecco quello che sto lavorando con e il violino:Collegamento dati all'interno della direttiva AngularJs

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

HTML:

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

direttiva:

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

Come ho tipo nella textarea, il modello non è l'aggiornamento come se ne avessi bisogno. Che cosa sto facendo di sbagliato?

risposta

0

Non ne sono del tutto sicuro, ma penso che quello che vuoi sia un filtro, dai un'occhiata a questo URL, forse è un ottimo approccio per ripensare al tuo problema.

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

+0

Non penso che sia quello con cui ho delle difficoltà qui. Il mio problema è piuttosto diretto. Sulla textarea, ho un modello assegnato. Il binding a 2 vie su quel modello si sta rompendo dopo aver abilitato la direttiva myMaxlength. – Dustin

5

non si ha realmente bisogno di una direttiva personalizzato? AngularJS viene fornito con una direttiva ngMaxlength che può essere utile con ngChange.

Ad esempio, se si ha il seguente codice 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> 

Poi basta bisogno di questo nel controller

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

Let angolare gestire il DOM per quanto è possibile.

Ecco il jsfiddle aggiornamento: http://jsfiddle.net/jaimem/ksb3j/7/

+0

Mi piacerebbe utilizzare la funzione angolare incorporata. Ma perché questo non impedisce la digitazione di caratteri aggiuntivi nella textarea? Questo è il comportamento che mi aspettavo da maxlength. –

12

Beh, ci sono due ragioni per cui il doppio senso di associazione dati non funziona. In primo luogo, è necessario creare un legame bidirezionale tra una proprietà ambito locale e la proprietà ambito padre:

scope: { bar: "=ngModel" } 

altrimenti si sta creando un ambito isolato (vedi http://docs.angularjs.org/guide/directive).

L'altra ragione è che si deve sostituire il dopo l'istruzione inserto con un accodamento dal genitore (perché si sta solo bootstrapping angolare dom.ready):

element.parent().append(counterElement); 

Aggiornamento jsfiddle: http://jsfiddle.net/andregoncalves/ksb3j/9/

+0

Come farei se non sapessi il nome del modello prima del tempo? Inoltre, perché hai bisogno di usare element.parent(). Append() invece di element.after()? – Dustin

+1

Se non si conosce in anticipo il nome del modello, è meglio non utilizzare la sintassi dichiarativa del modello ng e ottenere il modello dall'ambito del controller (impostare l'ambito su false nella direttiva). Per quanto riguarda element.parent(). Append(), è perché si sta solo eseguendo l'avvio angolare su dom.ready e quando la direttiva esegue il bootstrap non si è ancora verificato, rimuovilo dal gestore dom.ready e puoi usare dopo(). –

+0

Ok ho un violino aggiornato qui: http://jsfiddle.net/dkrotts/WWCzQ/3/. Il problema che sto avendo ora è che la mia variabile scope charsRemaining deve essere isolata nella direttiva in modo che possa usare questa direttiva più volte sulla stessa pagina. Come è ora (con scope: false), charsRemaining è condiviso attraverso l'ambito genitore e ho bisogno che quella specifica variabile sia isolata solo per la direttiva. – Dustin

Problemi correlati