Обновить модель Angular после установки значения ввода с помощью jQuery

У меня есть такой простой сценарий:

Элемент ввода, значение которого изменяется с помощью метода jQuery val().

Я пытаюсь обновить модель angular со значением, заданным jQuery. Я попытался написать простую директиву, но это не делает то, что я хочу.

Здесь директива:

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

это часть jQuery:

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

и html:

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

<button>clickme</button>

Вот скрипка с моей попыткой:
http://jsfiddle.net/U3pVM/743/

Кто-нибудь может указать мне в правильном направлении?

Ответ 1

ngModel прослушивает событие "ввода", поэтому для "исправления" вашего кода вам необходимо запустить это событие после установки значения:

$('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
});

Для объяснения этого конкретного поведения проверьте этот ответ, который я дал некоторое время назад: "Как AngularJS внутренне захватывает такие события, как "onclick" , "onchange" ?"


Но, к сожалению, это не единственная проблема, которая у вас есть. Как отмечалось в других комментариях к сообщениям, ваш подход, ориентированный на jQuery, совершенно неправильный. Для получения дополнительной информации см. Сообщение: Как мне "думать в AngularJS" , если у меня есть фон jQuery?).

Ответ 2

Надеюсь, это полезно для кого-то.

Мне не удалось получить событие jQuery('#myInputElement').trigger('input') для моего приложения angular.

Я мог, однако, получить angular.element(jQuery('#myInputElement')).triggerHandler('input').

Ответ 3

Я не думаю, что здесь требуется jQuery.

Вместо $watch и ng-click можно использовать

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

В вашем контроллере:

$scope.$watch('foo', function(newValue, oldValue) {
  console.log(newValue);
  console.log(oldValue);
});

Ответ 4

Вы должны использовать следующий код, чтобы обновить область конкретной модели ввода следующим образом

$('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;
    });
});

Ответ 5

Принятый ответ, который запускал событие input с jQuery, не работал у меня. Создание события и отправка с помощью встроенного JavaScript сделали трюк.

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

Ответ 6

Я вносил изменения только при инициализации контроллера, добавляя кнопку прослушивания на кнопку действия:

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

Другие решения в моем случае не работали.

Ответ 7

Я знаю, что это немного поздно, чтобы ответить здесь, но, возможно, я смогу сэкономить один раз в день.

Я имел дело с той же проблемой. Модель не будет заполняться после обновления значения ввода из jQuery. Я пробовал использовать триггерные события, но никаких результатов.

Вот что я сделал, что может спасти ваш день.

Объявить переменную в теге script в HTML.

Как

<script>
 var inputValue="";

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

</script>

Как только вы сделали это, используя ниже сервис angular.

$окно

Теперь ниже функция getData, вызванная из той же области контроллера, даст вам нужное значение.

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

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

$scope.getData = function () {
    console.log("Window value " + $window.inputValue);
}}]);

Ответ 8

Я написал этот маленький плагин для jQuery, который сделает все вызовы .val(value) обновленным элементом angular, если он есть:

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

Просто введите этот script в после jQuery и angular.js и val(value) обновления теперь должны играть хорошо.


Минимальная версия:

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

Пример:

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

Ответ 9

Если вы используете IE, вам нужно использовать: input.trigger( "change" );

Ответ 10

добавить .change() после установки значения.

Пример: ('id').val.('value').change();

также не забудьте добавить тег onchange или ng-change в html

Ответ 11

Я сделал это, чтобы иметь возможность обновить значение ngModel извне с помощью Vanilla/jQuery:

function getScope(fieldElement) {
    var $scope = angular.element(fieldElement).scope();
    var nameScope;
    var name = fieldElement.getAttribute('name');
    if($scope) {
        if($scope.form) {
            nameScope = $scope.form[name];
        } else if($scope[name]) {
            nameScope = $scope[name];
        }
    }
    return nameScope;
}

function setScopeValue(fieldElement, newValue) {
    var $scope = getScope(fieldElement);
    if($scope) {
        $scope.$setViewValue(newValue);
        $scope.$validate();
        $scope.$render();
    }
}

setScopeValue(document.getElementById("fieldId"), "new value");