2013-08-31 18 views
24

Sto provando a scrivere una direttiva che faccia uso dell'ambito isolato e della direttiva ngModel.Direttiva con campo di misura isolato e modello ng

Problema:
Quando il modello viene aggiornato nella direttiva, il valore del chiamante non viene aggiornato.

HTML:

<test-ng-model ng-model="model" name="myel"></test-ng-model> 

direttiva:

app.directive(
    'testNgModel', [ 
    '$timeout', 
    '$log', 

function ($timeout, $log) { 

    function link($scope, $element, attrs, ctrl) { 
     var counter1 = 0, counter2 = 0; 

     ctrl.$render = function() { 
      $element.find('.result').text(JSON.stringify(ctrl.$viewValue)) 
     } 

     $element.find('.one').click(function() { 
      if ($scope.$$phase) return; 
      $scope.$apply(function() { 
       var form = angular.isObject(ctrl.$viewValue) ? ctrl.$viewValue : {}; 
       form.counter1 = ++counter1; 
       ctrl.$setViewValue(form); 
      }); 
     }); 
     $element.find('.two').click(function() { 
      if ($scope.$$phase) return; 
      $scope.$apply(function() { 
       var form = angular.isObject(ctrl.$viewValue) ? ctrl.$viewValue : {}; 
       form.counter2 = ++counter2; 
       ctrl.$setViewValue(form); 
      }); 
     }); 

     $scope.$watch(attrs.ngModel, function (current, old) { 
      ctrl.$render() 
     }, true) 
    } 

    return { 
     require: 'ngModel', 
     restrict: 'E', 
     link: link, 
     //if isolated scope is not set it is working fine 
     scope: true, 
     template: '<div><input type="button" class="one" value="One"/><input type="button" class="two" value="Two"/><span class="result"></span></div>', 
     replace: true 
    }; 

}]); 

Demo: Fiddle

Se l'ambito isolato non è impostato funziona bene: fiddle

+1

'ambito: true' non crea un ambito isolato, si crea un nuovo ambito figlio che eredita prototipicamente dal campo di applicazione genitore, da qui il motivo '$ parent.model' funziona. (Un ambito isolato viene creato quando usiamo la sintassi 'scope: {...}' Qui viene anche creato un nuovo ambito figlio, ma esso non eredita prototipicamente dal genitore.) In generale, un ambito figlio dovrebbe essere utilizzato con ng-model poiché si sta creando un componente che deve interagire con altre direttive (ad esempio, ng-model). Quindi ti suggerisco di andare con il tuo secondo, funzionante, violino. –

+0

@MarkRajcok che non è un'opzione per me dal momento che la direttiva è più complessa e aggiunge alcuni attributi personalizzati all'ambito che porteranno all'inquinamento dello scope genitore –

+0

Ok, usa 'scope: true', ma usa anche un oggetto, non un primitivo: ''. [Violino] (http://jsfiddle.net/mrajcok/6ZaB5/). –

risposta

12

Come discusso nei commenti, non è generalmente raccomandato l'uso di un ambito bambino (o scope: truescope: { ... }) con ng-modello. Tuttavia, poiché Arun deve creare proprietà aggiuntive per l'ambito, è possibile utilizzare scope: true con un oggetto, non con una primitiva. Questo sfrutta l'ereditarietà prototipo, quindi non è $parent neeed:

<test-ng-model ng-model="someObj.model" ...> 

fiddle

+0

è possibile farlo funzionare con scope isolato invece del nuovo scope http://jsfiddle.net/arunpjohny/gbfNY/1/ –

+0

@ArunPJohny, l'ambito genitore non viene aggiornato - si noti che '{{someObj. modello | json}} L'output è vuoto. Per ulteriori informazioni su come gli ambiti isolati e ng-model non si mescolano, consultare http://stackoverflow.com/questions/11896732/ngmodel-and-component-with-isolated-scope. –

7

Perché si è creato un iso ambito limitato, ngModel = "modello" si riferisce al tuo nuovo ambito isolato. Se si vuole fare riferimento alla vostra portata AppController, si dovrebbe usare $ genitore:

<test-ng-model ng-model="$parent.model" name="myel"></test-ng-model> 
+2

'scope: true' non crea un ambito isolato. –

+0

Buon punto. La mia soluzione funzionerebbe comunque, anche se l'ambito non è isolato. Ma la soluzione che proponi è molto meglio. –

Problemi correlati