Cập nhật mô hình góc sau khi đặt giá trị đầu vào với jQuery


160

Tôi có kịch bản đơn giản này:

Phần tử đầu vào có giá trị được thay đổi bằng phương thức val () của jQuery.

Tôi đang cố gắng cập nhật mô hình góc với giá trị mà jQuery đặt. Tôi đã cố gắng viết một chỉ thị đơn giản, nhưng nó không làm những gì tôi muốn.

Đây là chỉ thị:

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

đây là phần jQuery:

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

và html:

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

<button>clickme</button>

Đây là câu đố với sự cố gắng của tôi:
http://jsfiddle.net/U3pVM/743/

Có thể ai đó xin vui lòng chỉ cho tôi đi đúng hướng?


2
Trộn AngularJS và jQuery, bên ngoài các chỉ thị, thường là một ý tưởng tồi. JQuery có bắt buộc cho những gì bạn muốn làm không?
Hố đen

Tại sao bạn không đặt sự kiện nhấp với góc tới một hàm trong bộ điều khiển để thay đổi giá trị của mô hình?
Jimmy Kane

@Blackhole, tôi đang sử dụng plugin tải lên jquery thực hiện công việc của nó và đặt đường dẫn đến tệp đã tải lên vào đầu vào ẩn. Tất cả tôi cần là có quyền truy cập vào con đường đó trong mô hình góc. Vì vậy, tôi nghĩ rằng tôi sẽ đặt nó làm giá trị của đầu vào ẩn và sau khi thay đổi, hãy cập nhật mô hình góc.
Michal J.

Tôi không thấy cuộc gọi của Jquery trong fiddle của bạn ... Bạn có thể kiểm tra và chỉ ra nơi bạn thay đổi giá trị với JQ không?
Valentyn Shybanov

Fiddle của bạn liên kết đến một ứng dụng mẫu Todo, không liên quan đến câu hỏi này.
Stewie

Câu trả lời:


322

ngModel lắng nghe sự kiện "đầu vào", vì vậy để "sửa" mã của bạn, bạn cần kích hoạt sự kiện đó sau khi đặt giá trị:

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

Để biết giải thích về hành vi cụ thể này, hãy xem câu trả lời mà tôi đã đưa ra trước đây: " AngularJS nội bộ nắm bắt các sự kiện như 'onclick', 'onchange' như thế nào? "


Nhưng thật không may, đây không phải là vấn đề duy nhất bạn có. Như đã chỉ ra với các bình luận bài viết khác, cách tiếp cận tập trung vào jQuery của bạn hoàn toàn sai. Để biết thêm thông tin, hãy xem bài đăng này: Tôi nghĩ thế nào về AngularJS ném nếu tôi có nền jQuery? ).


5
Mát mẻ! Với một ngoại lệ: tại sao nó không hoạt động trên các đầu vào ẩn? Khi tôi chuyển loại đầu vào của mình thành văn bản, nó sẽ hoạt động như mong đợi.
Karol

8
Điều này đã giải quyết một vấn đề lớn khi sử dụng các plugin lịch jquery. Bằng cách hack plugin để kích hoạt ('input') sau input.val (), sự kiện thay đổi ng sẽ kích hoạt sau khi người dùng chọn ngày theo lịch. Cảm ơn!
Drone Brain

3
Hoạt động hoàn hảo trên đầu vào ẩn: Element.triggerHandler ("thay đổi");
falko

2
Điều này không làm việc cho tôi. $ ("# Khoảng cách"). Val (dữ liệu); $ ("# Khoảng cách"). Kích hoạt ('đầu vào');
Stas Svishov

10
Với Angular 1.4.3, inputsự kiện không hoạt động trên IE bao gồm IE11. inputsự kiện chỉ hoạt động khi $sniff.hasEvent('input')đúng nhưng $sniff.hasEvent('input')sai ngay cả trên IE11! Chúng ta có thể sử dụng changesự kiện thay thế.
Shuhei Kagawa

61

Hy vọng điều này là hữu ích cho một ai đó.

Tôi đã không thể có được jQuery('#myInputElement').trigger('input')sự kiện để được chọn ứng dụng góc cạnh của tôi.

Tôi đã tuy nhiên, có thể angular.element(jQuery('#myInputElement')).triggerHandler('input')được nhận lên.


2
hãy giải thích giải pháp không chỉ viết mã. Tôi nhận được góc không phải là $ không phải là một chức năng
Thakhani Tharage 7/1/2015

1
$ đại diện cho jQuery ở đây. Nó được gắn thẻ trong câu hỏi.
ginman

Điều này cũng có hiệu quả với tôi trong khi $ ('myInputEuity'). Trình kích hoạt ('đầu vào') không ổn định. Nó dường như ngẫu nhiên làm việc đôi khi nhưng không phải người khác và tôi không bao giờ có thể thiết lập một mô hình. Giải pháp này hoạt động mọi lúc.
BryanP

2
Của tôi được làm việc với # tiền tố:angular.element($('#myInputElement')).triggerHandler('input')
Ebru Yener

Trình kích hoạt này cũng làm việc cho tôi, tôi đã xử lý văn bản không nhập liệu. Cảm ơn
Mounir

25

Câu trả lời được chấp nhận là inputsự kiện kích hoạt với jQuery không hoạt động với tôi. Tạo một sự kiện và gửi bằng JavaScript gốc đã thực hiện thủ thuật này.

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

Đây là giải pháp cho tôi quá. Sử dụng Angular 1.1.5, jQuery 2.2.4 và Jasmine 2.5.3. Rất, RẤT kỳ lạ mà không có cơ chế kích hoạt nào khác hoạt động.
Lars-Erik

Tôi đã tìm kiếm phương thức JS gốc để kích hoạt xác thực mẫu khi đặt đầu vào trong tập lệnh và điều này hiệu quả với tôi, cảm ơn.
phân tán

Hoạt động ngay cả với Angular 5, thật tuyệt!
Igor

Cảm ơn bạn. Đặc biệt hữu ích trong webview.evalujavascript
Berry Wing

22

Tôi không nghĩ jQuery là bắt buộc ở đây.

Bạn có thể sử dụng $ watchng-click thay thế

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

Trong bộ điều khiển của bạn:

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

1
Cảm ơn bạn Utopik, bạn đã đúng, tôi không nên kết hợp jquery với góc cạnh khi có một cách để thực hiện công việc bằng cách sử dụng góc.
Michal J.

17

Bạn phải sử dụng mã sau đây để cập nhật phạm vi của mô hình đầu vào cụ thể như sau

$('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; }); phần đó đã giúp tôi rất nhiều Vấn đề của tôi là cập nhật một mô hình góc cạnh sau một cuộc gọi ajax jquery trong chức năng thành công. Nó chậm với $ http vì có trình nghe sự kiện thay đổi trùng lặp cho phần tử đang làm một cái gì đó khác nên tôi đã hợp nhất nó vào jQuery.
Emmanuel Mahuni

1
Việc sử dụng Element.scope () là một ý tưởng tồi, bởi vì nó chỉ hoạt động khi đăng nhập được kích hoạt. Nếu bạn trên một trang web sản xuất, bạn nên tắt đăng nhập vào cấu hình của mình bằng $compileProvider.debugInfoEnabled(false);hoặc $logProvider.debugEnabled(false);Xem code.angularjs.org/1.4.0/docs/guide/production để biết thêm thông tin.
RWAM

Tôi đã thử phương pháp này cho biến ẩn và nó hoạt động. var li_cuboid_id = $ ('# li_cuboid_id'); li_cuboid_id.val (json.cuboidId) .change (); var scope = angular.element ($ ("# li_cuboid_id")). scope (); phạm vi. $ áp dụng (hàm () {scope.cuboidId = json.cuboidId;}); biến ẩn được định nghĩa là: <input id = "li_cuboid_id" type = hidden ng-model = "cuboidId">
Rahul Varadkar

7

Tôi đã thực hiện sửa đổi chỉ khởi tạo bộ điều khiển bằng cách thêm trình nghe trên nút hành động:

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

Các giải pháp khác không hoạt động trong trường hợp của tôi.


4

Tôi biết rằng hơi muộn để trả lời ở đây nhưng có lẽ tôi có thể tiết kiệm một số ngày.

Tôi đã được xử lý cùng một vấn đề. Một mô hình sẽ không được đưa vào khi bạn cập nhật giá trị đầu vào từ jQuery. Tôi đã thử sử dụng các sự kiện kích hoạt nhưng không có kết quả.

Đây là những gì tôi đã làm có thể tiết kiệm ngày của bạn.

Khai báo một biến trong thẻ script của bạn trong HTML.

Giống:

<script>
 var inputValue="";

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

</script>

Một khi bạn đã làm điều đó bằng cách sử dụng dịch vụ dưới đây của góc.

$ cửa sổ

Bây giờ bên dưới hàm getData được gọi từ cùng một phạm vi điều khiển sẽ cung cấp cho bạn giá trị bạn muốn.

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

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

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

3

Tôi đã viết plugin nhỏ này cho jQuery, nó sẽ thực hiện tất cả các lệnh gọi để .val(value)cập nhật phần tử góc nếu có:

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

Chỉ cần đưa tập lệnh này vào sau jQuery và angular.js và các val(value)bản cập nhật sẽ chơi tốt.


Phiên bản rút gọ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);

Thí dụ:


Xin lỗi vì đã đào sâu cái này lên, nhưng có ý tưởng nào về việc cái này sẽ / có thể hoạt động với hộp kiểm hoặc chọn vì chúng sử dụng .prop thay vì .val không? Điều này đang hoạt động hoàn hảo cho các thay đổi đầu vào .val ít nhất vì vậy cảm ơn bạn!
Austin

@Austin Tôi sợ tôi không biết. Đây là một câu hỏi 5 năm về hai công nghệ được coi là lỗi thời, vì vậy tôi không giữ được kiến ​​thức trong đầu. Tốt nhất của may mắn nhận được giải pháp bạn cần mặc dù.
dav_i

2

Nếu bạn đang sử dụng IE, bạn phải sử dụng: input.trigger ("thay đổi");


2

thêm .change()sau khi thiết lập giá trị.

thí dụ:('id').val.('value').change();

cũng đừng quên thêm onchangehoặc ng-changegắn thẻ trong html


0

Tôi đã làm điều này để có thể cập nhật giá trị của ngModel từ bên ngoài với 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");
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.