Оновіть кутову модель після встановлення вхідного значення за допомогою 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.