it-swarm.com.de

AngularJS: Die Bindung von ng-model wird nicht aktualisiert, wenn sie mit jQuery geändert wird

Das ist mein HTML:

<input id="selectedDueDate" type="text" ng-model="selectedDate" />

Wenn ich in die Box eintippe, wird das Modell über den 2-Wege-Bindungsmechanismus aktualisiert. Süss.

Allerdings wenn ich das über JQuery mache ...

$('#selectedDueDate').val(dateText);

Das Modell wird nicht aktualisiert. Warum?

97
Greg

Angular weiß nichts von dieser Änderung. Rufen Sie dazu $scope.$digest() auf oder nehmen Sie die Änderung in $scope.$apply() vor:

$scope.$apply(function() { 
   // every changes goes here
   $('#selectedDueDate').val(dateText); 
});

Sehen Sie this , um Dirty-Checkingbesser zu verstehen. _

UPDATE: Hier ist ein Beispiel

131

Benutz einfach; 

$('#selectedDueDate').val(dateText).trigger('input');
27
Jan Kuri

Ich habe festgestellt, dass die Variable zuverlässiger aktualisiert wird, wenn Sie die Variable nicht direkt mit dem Gültigkeitsbereich vergleichen.

Versuchen Sie es mit "dateObj.selectedDate" und fügen Sie im Controller das ausgewählte Date einem dateObj-Objekt hinzu:

$scope.dateObj = {selectedDate: new Date()}

Das hat bei mir funktioniert.

16
Ben Taliadoros

Versuche dies

var selectedDueDateField = document.getElementById("selectedDueDate");
var element = angular.element(selectedDueDateField);
element.val('new value here');
element.triggerHandler('input');
4
Ray

Führen Sie einfach die folgende Zeile am Ende Ihrer Funktion aus: 

$ scope. $ apply () 

2
Rohan M Nabar

Was auch immer außerhalb des Bereichs von Angular geschieht, das wird Angular niemals erfahren. 

Digest-Zyklus übernimmt die Änderungen vom Modell -> Controller und dann vom Controller -> Modell. 

Wenn Sie das neueste Modell sehen möchten, müssen Sie den Digest-Zyklus auslösen 

Es besteht jedoch die Chance, dass ein Verdauungszyklus im Gange ist. Daher müssen wir den Zyklus prüfen und initiieren.

Führen Sie vorzugsweise immer eine sichere Anwendung durch.

       $scope.safeApply = function(fn) {
            if (this.$root) {
                var phase = this.$root.$$phase;
                if (phase == '$apply' || phase == '$digest') {
                    if (fn && (typeof (fn) === 'function')) {
                        fn();
                    }
                } else {
                    this.$apply(fn);
                }
            }
        };


      $scope.safeApply(function(){
          // your function here.
      });

Sie müssen das change event des Eingabeelements auslösen, da ng-model Eingabeereignisse abhört und der Gültigkeitsbereich aktualisiert wird. Der regulärer jQuery-Trigger funktionierte jedoch nicht für mich. Aber hier funktioniert das wie ein Zauber

$("#myInput")[0].dispatchEvent(new Event("input", { bubbles: true })); //Works

Folgendes hat nicht funktioniert

$("#myInput").trigger("change"); // Did't work for me

Lesen Sie mehr über Erstellen und Versenden von synthetischen Ereignissen .

1
Hari Das

AngularJS übergibt String, Zahlen und Booleans nach Wert, während Arrays und Objekte als Referenz übergeben werden. So können Sie ein leeres Objekt erstellen und Ihr Datum zu einer Eigenschaft dieses Objekts machen. Auf diese Weise erkennt Winkel Modelländerungen.

Im Controller

app.module('yourModule').controller('yourController',function($scope){
$scope.vm={selectedDate:''}
});

In HTML

<div ng-controller="yourController">
<input id="selectedDueDate" type="text" ng-model="vm.selectedDate" />
</div>
1
Himanshu Mittal

Benutz einfach:

$('#selectedDueDate').val(dateText).trigger('input');

anstatt:

$('#selectedDueDate').val(dateText);
0
Wekerle Tibor

Ich habe dieses kleine Plugin für jQuery geschrieben, das alle Aufrufe an .val(value) vornimmt, um das Winkelelement zu aktualisieren, falls vorhanden:

(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);

Fügen Sie dieses Skript einfach ein, nachdem jQuery und angle.js und val(value)-Updates jetzt Nice gespielt haben.


Reduzierte Version:

!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);

Beispiel:

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


Diese Antwort wurde wörtlich aus meiner Antwort auf eine ähnliche Frage kopiert.

0
dav_i