Mettre à jour le modèle angulaire après avoir défini la valeur d'entrée avec jQuery

j'ai ce scénario simple:

élément D'entrée dont la valeur est changée par la méthode val() de jQuery.

j'essaie de mettre à jour le modèle angulaire avec la valeur que jQuery a définie. J'ai essayé d'écrire une simple directive, mais elle ne fait pas ce que je veux.

Voici la directive:

var myApp = angular.module('myApp', []);
myApp.directive('testChange', function() {
    return function(scope, element, attrs) {        
        element.bind('change', function() {
            console.log('value changed');
        })
    }
})

c'est la partie jQuery:

$(function(){
    $('button').click(function(){
        $('input').val('xxx');
    })
})

et html:

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <input test-change ng-model="foo" />
        <span>{{foo}}</span>
    </div>
</div>

<button>clickme</button>

voici le violon avec mon essai:

http://jsfiddle.net/U3pVM/743 /

quelqu'un peut-il m'indiquer la bonne direction?

146
demandé sur Philip Kirkbride 2013-06-14 17:39:22

10 réponses

ngModel écoute pour l'événement "input" , donc pour "corriger" votre code vous devez déclencher cet événement après avoir défini la valeur:

$('button').click(function(){
    var input = $('input');
    input.val('xxx');
    input.trigger('input'); // Use for Chrome/Firefox/Edge
    input.trigger('change'); // Use for Chrome/Firefox/Edge + IE11
});

pour l'explication de ce comportement particulier, consultez la réponse que j'ai donnée il y a un certain temps: " comment les AngularJS saisissent-ils à l'interne des événements comme "onclick", "onchange"? "


Mais malheureusement, ce n'est pas le seul problème que vous avez. Comme l'a souligné avec autres commentaires postés, votre approche jQuery-centric est clairement erronée. Pour plus d'info jetez un oeil à ce post: Comment puis-je "penser en AngularJS" si j'ai une formation jQuery? ).

305
répondu Stewie 2017-05-23 11:47:29

J'espère que c'est utile pour quelqu'un.

j'ai été incapable d'obtenir l'événement jQuery('#myInputElement').trigger('input') pour être ramassé mon application angulaire.

j'ai cependant réussi à faire ramasser angular.element(jQuery('#myInputElement')).triggerHandler('input') .

57
répondu ginman 2016-03-18 08:01:36

Je ne pense pas que jQuery soit nécessaire ici.

vous pouvez utiliser $ watch et ng-click à la place

<div ng-app="myApp">
  <div ng-controller="MyCtrl">
    <input test-change ng-model="foo" />
    <span>{{foo}}</span>

    <button ng-click=" foo= 'xxx' ">click me</button>
    <!-- this changes foo value, you can also call a function from your controller -->
  </div>
</div>

dans votre contrôleur:

$scope.$watch('foo', function(newValue, oldValue) {
  console.log(newValue);
  console.log(oldValue);
});
22
répondu Utopik 2013-06-14 14:44:27

vous devez utiliser le code suivant afin de mettre à jour la portée du modèle d'entrée spécifique comme suit

$('button').on('click', function(){
    var newVal = $(this).data('val');
    $('select').val(newVal).change();

    var scope = angular.element($("select")).scope();
    scope.$apply(function(){
        scope.selectValue = newVal;
    });
});
17
répondu jayM 2014-03-05 15:54:16

la réponse acceptée qui déclenchait l'événement input avec jQuery ne marchait pas pour moi. La création d'un événement et l'envoi avec JavaScript natif ont fait l'affaire.

$("input")[0].dispatchEvent(new Event("input", { bubbles: true }));
9
répondu Martins Balodis 2017-01-11 14:11:23

j'ai fait des modifications sur la seule initialisation du contrôleur en ajoutant l'auditeur sur le bouton d'action:

$(document).on('click', '#action-button', function () {
        $timeout(function () {
             angular.element($('#input')).triggerHandler('input');
        });
});

d'Autres solutions n'ont pas fonctionné dans mon cas.

7
répondu Ebru Yener 2015-12-13 21:25:31

je sais qu'il est un peu tard pour répondre ici, mais peut-être que je peux en sauver quelques-uns une fois par jour.

j'ai fait face au même problème. Un modèle ne sera pas peuplé une fois que vous aurez mis à jour la valeur des entrées de jQuery. J'ai essayé d'utiliser des événements déclencheurs mais aucun résultat.

voici ce que j'ai fait qui pourrait sauver votre journée.

déclare une variable dans votre étiquette de script en HTML.

Comme:

<script>
 var inputValue="";

// update that variable using your jQuery function with appropriate value, you want...

</script>

une fois que vous avez fait cela en utilisant ci-dessous le service d'angle.

"151920920 $" de la fenêtre

maintenant ci-dessous la fonction getData appelée à partir du même contrôleur scope vous donnera la valeur que vous voulez.

var myApp = angular.module('myApp', []);

app.controller('imageManagerCtrl',['$scope','$window',function($scope,$window) {

$scope.getData = function () {
    console.log("Window value " + $window.inputValue);
}}]);
3
répondu Khawaja Asim 2017-03-02 08:24:29

j'ai écrit ce petit plugin pour jQuery qui fera tous les appels à .val(value) mettre à jour l'élément angulaire si présent:

(function($, ng) {
  'use strict';

  var $val = $.fn.val; // save original jQuery function

  // override jQuery function
  $.fn.val = function (value) {
    // if getter, just return original
    if (!arguments.length) {
      return $val.call(this);
    }

    // get result of original function
    var result = $val.call(this, value);

    // trigger angular input (this[0] is the DOM object)
    ng.element(this[0]).triggerHandler('input');

    // return the original result
    return result; 
  }
})(window.jQuery, window.angular);

Ecrivez juste ce script après jQuery et angular.les mises à jour de js et val(value) devraient maintenant être agréables.


version Minifiée:

!function(n,t){"use strict";var r=n.fn.val;n.fn.val=function(n){if(!arguments.length)return r.call(this);var e=r.call(this,n);return t.element(this[0]).triggerHandler("input"),e}}(window.jQuery,window.angular);

exemple:

// the function
(function($, ng) {
  'use strict';
  
  var $val = $.fn.val;
  
  $.fn.val = function (value) {
    if (!arguments.length) {
      return $val.call(this);
    }
    
    var result = $val.call(this, value);
    
    ng.element(this[0]).triggerHandler('input');
    
    return result;
    
  }
})(window.jQuery, window.angular);

(function(ng){ 
  ng.module('example', [])
    .controller('ExampleController', function($scope) {
      $scope.output = "output";
      
      $scope.change = function() {
        $scope.output = "" + $scope.input;
      }
    });
})(window.angular);

(function($){  
  $(function() {
    var button = $('#button');
  
    if (button.length)
      console.log('hello, button');
    
    button.click(function() {
      var input = $('#input');
      
      var value = parseInt(input.val());
      value = isNaN(value) ? 0 : value;
      
      input.val(value + 1);
    });
  });
})(window.jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="example" ng-controller="ExampleController">
  <input type="number" id="input" ng-model="input" ng-change="change()" />
  <span>{{output}}</span>
  <button id="button">+</button>
</div>
2
répondu dav_i 2015-03-12 17:54:04

Si vous utilisez IE, vous devez utiliser: entrée.trigger("changement");

2
répondu William 2016-06-29 00:54:09

ajouter .change() après avoir fixé la valeur.

exemple: ('id').val.('value').change();

aussi n'oubliez pas d'ajouter onchange ou ng-change étiquette en html

2
répondu Azeez 2016-10-20 07:51:42