AngularJS : ng-modelo de enlace no se actualiza cuando se cambia con jQuery

Este es mi código HTML:

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

Cuando yo escriba en el cuadro, el modelo se actualiza a través de la 2-forma-el mecanismo de unión. Dulce.

Sin embargo cuando hago esto a través de JQuery…

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

No actualizar el modelo. Por qué?

  • ¿Por qué hacer el segundo uno, para empezar ? Estás usando un marco de trabajo y, a continuación, decidir prescindir de ella y establecer el valor a través de la manipulación del árbol DOM. El mejor consejo que se puede dar con angular para principiantes: olvidar jquery existe. en el 90% de los casos angular será suficiente y el 10% restante puede ser logrado a través de jqlite dentro de una directiva del enlace (elemento es en realidad un jqlite envuelto elemento listo para ser manipulado).
  • pregunta muy importante
  • hay muy buenas razones por las que es posible que desee cambiar angular de los modelos con la manipulación del árbol dom, tal vez usted es un desarrollador que trabaja con un A/B testing herramienta y quieres rellenar los formularios detrás de las escenas, o estás trabajando en un script de greasemonkey para autocompletar formularios.
InformationsquelleAutor Greg | 2012-08-08

10 Kommentare

  1. 133

    Angular no sabe acerca de ese cambio. Para esto, usted debe llamar a $scope.$digest() o realizar el cambio dentro de $scope.$apply():

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

    Ver este para entender mejor sucio de comprobación de

    ACTUALIZACIÓN: Aquí es un ejemplo

    • Hice esto como usted dice: fiddle.jshell.net/AladdinMhaimeed/agvTz/8 pero no funciona
    • Ver este fiddle.jshell.net/agvTz/38 Usted debe llamar a la function $scope.$aplicar pasar una función como argumento. Y $aplican deben ser llamada cuando se hacen los cambios en $alcance, por lo tanto, dentro de onSelect. Ah, espero que te ponga de manipulación DOM dentro de controlador sólo para el ejemplo, en una aplicación real, esto está mal 😉
    • entonces, ¿qué debo hacer para hacer un buen angular de la práctica? aparte de manipulación DOM en una directiva?
    • Sí, aquí un ejemplo de fiddle.jshell.net/agvTz/39 la directiva puede ser utilizado tantas veces como uno desee con un simple datepicker="scopeKeyThatYouWant" en la entrada
    • Simplemente llame a.. $scope.$digest() para resolver. va a bajar ?
    • Esto es perfecto. Para agregar, este es también el caso para la situación inversa. Cuando el cambio angular valor en javascript también el uso de ‘$scope.$digest()’ para ver la actualización en su cuadro de texto de entrada.
    • no es un problema si queremos añadir el segundo elemento. compruebe esto hacia fuera fiddle.jshell.net/agvTz/378

  2. 28

    Solo uso;

    $('#selectedDueDate').val(dateText).trigger('input');
    • He utilizado trigger('input') con un selector de fecha en su onSelect evento. Se actualiza el valor correctamente.
    • Esto hizo que el truco para mí. Yo estaba actualizando el valor de un límite de entrada de una directiva de la prueba y envolver el .val('something' llamada en un $apply (o llamando $digest después) no funciona.
    • Después de horas de búsqueda, este fue el único que funcionó! Gracias!
    • No funciona en Internet Explorer 11 para mí 🙁
    • Gracias a dios, perfecto su trabajo para mí. gracias a salvar a mis horas
    • Verdadero. Yo estaba usando $('#selectedDueDate').val(dateText).trigger('change'); que no estaba funcionando para mí. .trigger('input'); funciona como magia

  3. 16

    He encontrado que si usted no pone la variable directamente contra el ámbito de aplicación se actualiza de forma más fiable.

    Pruebe a utilizar algunos «dateObj.selectedDate» y en el controlador de agregar el selectedDate a un dateObj objeto así:

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

    Esto funcionó para mí.

    • Esto funcionó para mí. Yo había desperdiciado más de 2 horas tratando de averiguar por qué dos vías de enlace no funcionaba. Funcionó bien en la página, pero el ámbito en el que el controlador no estaba siendo actualizado. Entonces traté de su enfoque de la desesperación (porque no tenía ningún sentido para mí que esto debe ser cierto) y caliente maldita sea, ¡funcionó! Gracias!
    • Mismo aquí – cualquier angularJs gurú de explicar por qué funciona esto? Es como el vista tiene su propia anidada alcance y a veces te quedas atascado actualizando la vista-ámbito de aplicación, no el controlador de alcance
    • Funciona bien para mí! Me pregunto por qué carajo no funcionan de la misma en el mismo ámbito.
    • Tiene poco que ver con angular, y mucho que ver con cómo funciona javascript. Cuando se asigna el alcance de la variable de un objeto, la asignación por referencia, en lugar de valor como se hace cuando un var es igual a un valor primitivo. Hablé de ello en mi post aquí. stackoverflow.com/questions/14527377/…. Yo hice referencia a este plunk hice en ese puesto para ilustrar plnkr.co/editar/WkCT6aYao3qCmzJ8t5xg?p=vista previa.
  4. 4

    Probar este

    var selectedDueDateField = document.getElementById("selectedDueDate");
    var element = angular.element(selectedDueDateField);
    element.val('new value here');
    element.triggerHandler('input');
    • Es útil cuando usted no tiene el acceso a la angulares del controlador de $scope. Cuando se escribe un guión con un Tampermonkey, por ejemplo.
  5. 2

    Lo que sucede fuera del Ámbito de aplicación de Angular, Angular nunca va a saber que.

    Digerir ciclo de poner los cambios desde el modelo -> controlador y, a continuación, a partir de controlador -> el modelo.

    Si usted necesita para ver el último Modelo, usted necesita para activar la síntesis de ciclo

    Pero hay una probabilidad de un compendio de ciclo en curso, por lo que debemos revisar y inicio el ciclo.

    De preferencia, realizar siempre un seguro de aplicar.

           $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.
          });
  6. 1

    AngularJS pase las cadenas, números y booleanos por valor mientras se pasa las matrices y objetos por referencia. Así que usted puede crear un objeto vacío y hacer que su fecha de una propiedad de ese objeto. En que forma angular detectar cambios en el modelo.

    Controlador

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

    En html

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

    Tienes que activar la evento de cambio de del elemento de entrada porque ng-model escucha a los eventos de entrada y el ámbito de aplicación será actualizada. Sin embargo, la regular jQuery disparador no funciona para mí. Pero aquí es lo que funciona como un encanto

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

    Siguiente no funciona

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

    Usted puede leer más acerca de creación y envío de sintético eventos.

  8. 0

    He escrito este pequeño plugin para jQuery que hará que todas las llamadas a .val(value) actualización de la angulares elemento si está presente:

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

    Pop esta secuencia de comandos después de jQuery y angular.js y val(value) actualizaciones deberían jugar bonito.


    Record de versión:

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

    Ejemplo:

    JS:

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

    HTML:

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


    Esta respuesta fue copiado textualmente de mi respuesta a otra pregunta similar.

  9. 0

    Sólo tiene que utilizar:

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

    lugar de:

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

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea