Оновіть кутову модель після встановлення вхідного значення за допомогою jQuery


160

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

Елемент введення, значення якого змінюється методом jQuery's val ().

Я намагаюся оновити кутову модель зі значенням, встановленим 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/

Може хтось, будь ласка, вказав мене в правильному напрямку?


2
Змішання AngularJS та jQuery, поза директивами, часто є поганою ідеєю. Чи обов'язковий jQuery для того, що ви хочете зробити?
— Blackhole

Чому б вам не встановити подію клацання з кутовою функцією в контролері, щоб змінити значення моделі?
— Джиммі Кейн

@Blackhole, я використовую плагін для завантаження jquery, який виконує свою роботу і ставить шлях до завантаженого файлу до прихованого вводу. Все, що мені потрібно - це мати доступ до цього шляху в кутовій моделі. Тому я подумав, що встановлю це як значення прихованого вводу, і після його зміни оновіть кутову модель.
— Michal J.

Я не бачу дзвінка Jquery у вашій скрипці ... Чи можете ви перевірити та вказати, де ви змінюєте значення за допомогою JQ?
— Валентин Шибанов

Ваша скрипка посилається на зразок програми Todo, який не стосується цього питання.
— Стюі

Відповіді:


322

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? ).


5
Класно! За винятком: чому він не працює на прихованих входах? Коли я перемикаю тип введення на текст, він працює як очікувалося.
— Кароль

8
Це вирішило головну проблему при використанні плагінів календаря jquery. Зловмивши плагін для запуску ('input') після input.val (), подія ng-зміни спрацьовує після вибору користувачем дати календаря. Дякую!
— Drone Brain

3
Працює ідеально на прихованому вході: element.triggerHandler ("змінити");
— falko

2
це не працює для мене. $ ("# Відстань"). Val (дані); $ ("# Відстань"). Тригер ("вхід");
— Стас Свішов

10
З кутовим 1.4.3 inputподія не працює на IE, включаючи IE11. inputподія працює лише тоді, коли $sniff.hasEvent('input')це правда, але $sniff.hasEvent('input')є помилковою навіть на IE11! Ми можемо використовувати changeподію замість цього.
— Shuhei Kagawa

61

Сподіваюся, це комусь корисно.

Мені не вдалося змусити jQuery('#myInputElement').trigger('input')подію забрати мою кутову програму.

Однак мені вдалося забрати мене angular.element(jQuery('#myInputElement')).triggerHandler('input').


2
Будь ласка, поясніть рішення не просто пишіть код. я
— кутий

1
$ представляє jQuery тут. Це позначено у питанні.
— ginman

Це працювало і для мене, поки $ ('myInputElement'). Тригер ('input') був лускатим. Здавалося, що випадково працює іноді, але не інші, і я ніколи не міг встановити схему. Це рішення працює щоразу.
— BryanP

2
Моя робота працює з # префіксом:angular.element($('#myInputElement')).triggerHandler('input')
— Ебру Єнер,

Цей тригерHandler працював і на мене, я мав справу з textarea not input. Спасибі
— Мунір

25

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

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

Це було рішення і для мене. Використовуючи Angular 1.1.5, jQuery 2.2.4 та Жасмін 2.5.3. Дуже дивно, що не спрацьовують інші механізми спрацьовування.
— Ларс-Ерік

Я шукав рідний метод JS для запуску перевірки форми при встановленні вводу в сценарій, і це працювало для мене, дякую.
— розійтися

Працює навіть з кутовим 5, чудово!
— Ігор

Дякую. Особливо корисний webview.evaluatejavascript
— Беррі Вінг

22

Я не думаю, що тут потрібен 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);
});

1
Дякую, Utopik, ти маєш рацію, я не повинен змішувати jquery з angular, коли є спосіб, як виконати роботу за допомогою angular.
— Michal J.

17

Для оновлення сфери застосування конкретної вхідної моделі вам потрібно використовувати наступний код наступним чином

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

1
var scope = angular.element($("select")).scope(); scope.$apply(function(){ scope.selectValue = newVal; }); ця порція мені дуже допомогла. Моя проблема полягала в оновленні кутової моделі після виклику jquery ajax у функції успіху. Це було повільно з $ http, тому що для елемента, який робив щось інше, був дублюючий слухач подій зміни, тому я об'єднав його в jQuery.
— Еммануель Махуні

1
Використання element.scope () - погана ідея, оскільки він працює лише з увімкненим журналом. Якщо ви знаходитесь на виробничому сайті, вам слід вимкнути вхід у ваш конфігурацію за допомогою $compileProvider.debugInfoEnabled(false);або $logProvider.debugEnabled(false);Перегляньте code.angularjs.org/1.4.0/docs/guide/production для отримання додаткової інформації.
— RWAM

Я спробував цей метод для прихованої змінної, і він спрацював. var li_cuboid_id = $ ('# li_cuboid_id'); li_cuboid_id.val (json.cuboidId) .change (); var область = angular.element ($ ("# li_cuboid_id")). Oblast (); $ apply (function () {obseg.cuboidId = json.cuboidId;}); приховану змінну визначають як: <input id = "li_cuboid_id" type = hidden ng-model = "cuboidId">
— Rahul Varadkar

7

Я змінив лише ініціалізацію контролера, додавши слухача на кнопку дії:

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

Інші рішення не спрацювали в моєму випадку.


4

Я знаю, що тут відповісти трохи пізно, але, можливо, я можу врятувати одного разу.

Я мав справу з тією ж проблемою. Модель не заповнюватиметься, коли ви оновите значення вводу з jQuery. Я спробував використовувати події тригера, але результату немає.

Ось що я зробив, що може врятувати ваш день.

Оголосіть змінну в тезі сценарію в HTML.

Подібно до:

<script>
 var inputValue="";

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

</script>

Як тільки ви це зробили, скориставшись нижче службою кутового.

$ вікно

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

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

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

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

3

Я написав цей маленький плагін для jQuery, який змусить усі виклики .val(value)оновити кутовий елемент, якщо він присутній:

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

Просто запустіть цей сценарій після 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);

Приклад:


Вибачте за те, що це викопано, але будь-яка ідея, як це / могло б працювати з прапором або вибирати, оскільки вони використовують .prop замість .val? Це прекрасно працює для введення змін .val принаймні, тому дякую!
— Остін

@Austin Боюся, я не знаю. Це 5-річне запитання про дві технології, які широко вважаються застарілими, тому я не тримав своїх знань в голові. Найбільше удачі отримати рішення, яке вам потрібно.
— dav_i

2

Якщо ви використовуєте IE, ви повинні використовувати: input.trigger ("змінити");


2

додати .change() після встановлення значення.

приклад:('id').val.('value').change();

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


0

Я зробив це, щоб мати можливість оновити значення 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");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.