web-dev-qa-db-fra.com

AngularJS - Comment changer la valeur de ngModel dans une directive personnalisée?

Regardons ma directive:

angular.module('main').directive('datepicker', [
function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, ngModel) {
            ngModel.$modelValue = 'abc'; // this does not work
            // how do I change the value of the model?

Alors, comment puis-je changer la valeur du modèle ng?

42
Sady

Il y a différentes façons de le faire:

  1. $setViewValue() met à jour la vue et le modèle. Dans la plupart des cas, cela suffit.
  2. Si vous souhaitez déconnecter la vue du modèle (par exemple, le modèle est un nombre mais la vue est une chaîne avec des séparateurs de milliers), vous pouvez accéder directement à $viewValue et $modelValue
  3. Si vous souhaitez également écraser le contenu de ng-model (par exemple, la directive modifie le nombre de décimales et met également à jour le modèle), injecter ngModel: '=' sur le scope et set scope.ngModel

par exemple.

  return {
     restrict: 'A',
     require: 'ngModel',
     scope: {
         ngModel: '='
     },
     link: function (scope, element, attrs, ngModelCtrl) {

        function updateView(value) {
            ngModelCtrl.$viewValue = value;
            ngModelCtrl.$render(); 
        }

        function updateModel(value) {
            ngModelCtrl.$modelValue = value;
            scope.ngModel = value; // overwrites ngModel value
        }
 ...

LIENS:

49
Carlos Barcelona

Pour travailler avec des expressions de liaison complexes, vous devez utiliser le service $ parse et la méthode assign.

Pour plus d'informations, regardez cette vidéo de ng-conf - tout ce que vous pouvez faire avec la directive ng-model est génial: https://www.youtube.com/watch?v=jVzymluqmg4

app.directive('datepicker', ['$parse',
    function($parse) {
        return {
            require: '?ngModel',
            link: function(scope, element, attributes, controller) {
                // $parse works out how to get the value.
                // This returns a function that returns the result of your ng-model expression.
                var modelGetter = $parse(attributes['ngModel']);
                console.log(modelGetter(scope));

                // This returns a function that lets us set the value of the ng-model binding expression:
                var modelSetter = modelGetter.assign;

                // This is how you can use it to set the value 'bar' on the given scope.
                modelSetter(scope, 'bar');

                console.log(modelGetter(scope));
            }
        };
    }
]);
28
Sly_cardinal

Ce que vous avez essayé fonctionne réellement: voir ce Plunker

Vous ne le "voyez" pas dans l'entrée car changer le modèle de cette façon n'appelle pas controller.$render() pour définir le nouveau controller.$viewValue.

Mais pourquoi ne changez-vous pas simplement le $scope valeur (à moins que vous ne le sachiez pas, mais ce serait bizarre):

angular.module('main').directive('datepicker', [function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, controller) {
          var model = attributes['ngModel'];
          scope[model] = 'bar';
        }
    };
}]);

Et dans votre html:

<input ng-model="yourVariable" datepicker>

EDIT: (solution dynamique)

angular.module('main').directive('datepicker', [function() {
    return {
        require: '?ngModel',
        link: function(scope, element, attributes, controller) {
          // get the value of the `ng-model` attribute
          var model = attributes['ngModel'];

          // update the scope if model is defined
          if (model) {
            scope[model] = 'bar';
          }
        }
    };
}]);
4
glepretre

Cela fonctionne pour un DatePicker sur mon site

link: function(scope, elem, attrs, ngModel) {
         scope.$apply(function(){
             ngModel.$viewValue = value;
         }
} 
1
dball

Voici la meilleure explication que j'ai rencontrée. Cela m'a aidé beaucoup et rassemble les détails d'un certain nombre d'autres réponses ici.

CONSEIL: veillez à lire l'intégralité de l'article au lieu de l'écrémer, sinon vous risquez de manquer des informations essentielles!

https://www.nadeau.tv/post/using-ngmodelcontroller-with-custom-directives/

1
John Rix