Angularjs: input [text] ngChange kích hoạt khi giá trị đang thay đổi


92

ngChange đang kích hoạt trong khi giá trị đang thay đổi (ngChange không giống với sự kiện onChange cổ điển). Làm cách nào để liên kết sự kiện onChange cổ điển với anglejs, sự kiện sẽ chỉ kích hoạt khi nội dung được cam kết?

Ràng buộc hiện tại:

<input type="text" ng-model="name" ng-change="update()" />

Chỉ cần tìm kiếm một cái gì đó tương tự và điều đó xảy ra với tôi rằng bạn cũng có thể muốn xem xét cập nhật chỉ khi trường hợp lệ. Bằng cách đó, người dùng có thể đấu tranh với việc đưa đầu vào ở định dạng hợp lệ (hoặc bạn có thể giúp họ bằng lời nhắc và bộ lọc), sau đó bạn có thể thưởng cho họ một bản cập nhật khi họ làm đúng!
Steve Black,

Một giải pháp linh hoạt hơn nhiều cho phép chỉ định sự kiện để sử dụng (không chỉ làm mờ) và các thuộc tính khác sẽ sớm được tích hợp vào góc độ: github.com/angular/angular.js/pull/2129
wired_in

Câu trả lời:


96

Bài đăng này cho thấy một ví dụ về chỉ thị trì hoãn việc thay đổi mô hình thành đầu vào cho đến khi sự kiện mờ kích hoạt.

Đây là một thao tác hiển thị cho thấy ng-change hoạt động với chỉ thị ng-model-on-fade mới. Lưu ý rằng đây là một chỉnh sửa nhỏ cho fiddle ban đầu .

Nếu bạn thêm chỉ thị vào mã của mình, bạn sẽ thay đổi ràng buộc của mình với điều này:

<input type="text" ng-model="name" ng-model-onblur ng-change="update()" />

Đây là chỉ thị:

// override the default input to update on blur
angular.module('app', []).directive('ngModelOnblur', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        priority: 1, // needed for angular 1.2.x
        link: function(scope, elm, attr, ngModelCtrl) {
            if (attr.type === 'radio' || attr.type === 'checkbox') return;

            elm.unbind('input').unbind('keydown').unbind('change');
            elm.bind('blur', function() {
                scope.$apply(function() {
                    ngModelCtrl.$setViewValue(elm.val());
                });         
            });
        }
    };
});

Lưu ý: như @wjin đã đề cập trong các nhận xét bên dưới, tính năng này được hỗ trợ trực tiếp trong Angular 1.3 (hiện đang trong giai đoạn thử nghiệm) thông qua ngModelOptions. Xem tài liệu để biết thêm thông tin.


1
Thận trọng, elm.unbind ('input') ném 'TypeError' trong Internet Explorer 8 để các câu lệnh hủy liên kết khác sẽ không được thực thi. Tôi đã giải quyết nó bằng cách di chuyển elm.unbind ('input') sang một dòng riêng biệt và bao quanh nó bằng một khối try / catch.
Rob Juurlink

1
Angular 1.2 có một ng-blurchỉ thị: docs.angularjs.org/api/ng.directive:ngBlur
JJ Zabkar

5
Tôi đã làm cho mã này hoạt động, nhưng tôi phải đặt mức độ ưu tiên của chỉ thị (tức là, độ ưu tiên: 100). Tôi đang sử dụng Angular 1.2.10. Tôi đoán là chỉ thị ngModelOnblur đã chạy trước chỉ thị ngModel nên chưa có gì để hủy liên kết. Ngoài ra, trang này làm cho nó có vẻ như có thể có tích hợp sẵn trong dung dịch cho điều này trong tương lai: github.com/angular/angular.js/pull/1783
Alan Tây

4
LƯU Ý Ít nhất ở góc 1.3, chức năng này được hỗ trợ trong việc triển khai mặc định thông qua ng-model-options="{ updateOn: 'default blur' }"Xem tài liệu
wjin

2
@RobJuurlink (hoặc bất kỳ ai khác gặp phải 'TypeError' của IE8 khi cố gắng liên kết hoặc hủy liên kết với 'đầu vào') - Nhìn vào nguồn của Angular, bạn sẽ thấy rằng họ sử dụng $snifferđể xác định xem trình duyệt có hỗ trợ 'đầu vào' hay không và nếu không, họ rơi trở lại 'keydown'. Nếu bạn cập nhật các chỉ thị ở trên để chỉ unbind 'đầu vào' nếu $sniffer.hasEvent('input')trả về true - sau đó bạn có thể tránh được rằng lỗi và vẫn làm việc trong IE8
bvaughn

32

Đây là về các bổ sung gần đây cho AngularJS, để phục vụ như câu trả lời trong tương lai (cũng cho một câu hỏi khác ).

Angular phiên bản mới hơn (bây giờ là 1.3 beta), AngularJS nguyên bản hỗ trợ tùy chọn này, sử dụng ngModelOptions, như

ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"

Tài liệu NgModelOptions

Thí dụ:

<input type="text" name="username"
       ng-model="user.name"
       ng-model-options="{updateOn: 'default blur', debounce: {default: 500, blur: 0} }" />

Nó không làm việc đúng trong 1.3 beta 5, nhưng cố định trong hiện tại chủ build 2602
manikanta

Và đó là lý do tại sao nó vẫn đang trong giai đoạn thử nghiệm và không thể sử dụng được trong các ứng dụng "thế giới thực", chẳng hạn như ứng dụng mà tôi đang xây dựng ngay bây giờ.
reaper_unique

Dưới đây là một ng-mô hình các tùy chọn như mô-đun cho 1.2.x góc github.com/fergaldoyle/modelOptions
Fergal

8

Trong trường hợp bất kỳ ai khác đang tìm kiếm hỗ trợ nhấn phím "enter" bổ sung, đây là bản cập nhật cho fiddle do Gloppy cung cấp

Mã cho liên kết nhấn phím:

elm.bind("keydown keypress", function(event) {
    if (event.which === 13) {
        scope.$apply(function() {
            ngModelCtrl.$setViewValue(elm.val());
        });
    }
});

5

Đối với bất kỳ ai đang gặp khó khăn với IE8 (nó không thích unbind ('đầu vào'), tôi đã tìm ra cách giải quyết vấn đề này.

Chèn $ sniper vào chỉ thị của bạn và sử dụng:

if($sniffer.hasEvent('input')){
    elm.unbind('input');
}

IE8 bình tĩnh lại nếu bạn làm điều này :)


hoặc chỉ sử dụng try / catch
wired_in

4

Theo hiểu biết của tôi, chúng ta nên sử dụng ng-change với tùy chọn select và trong trường hợp hộp văn bản, chúng ta nên sử dụng ng-blur.


Đây là câu trả lời chính xác bây giờ, hồi đó khi câu hỏi được hỏi, nó dường như không tồn tại.
xuôi tay

Thank you very much ... đây sẽ là câu trả lời
Renjith


0

Ghi đè hành vi onChange đầu vào mặc định (chỉ gọi hàm khi điều khiển mất tiêu điểm và giá trị thay đổi)

LƯU Ý: ngChange không tương tự như sự kiện onChange cổ điển, nó kích hoạt sự kiện trong khi giá trị đang thay đổi Chỉ thị này lưu trữ giá trị của phần tử khi nó lấy tiêu điểm. Làm
mờ nó kiểm tra xem giá trị mới có thay đổi không và nếu có thì nó kích hoạt sự kiện

@param {String} - tên hàm sẽ được gọi khi "onChange" được kích hoạt

@example <input my-on-change = "myFunc" ng-model = "model">

angular.module('app', []).directive('myOnChange', function () { 
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            myOnChange: '='
        },
        link: function (scope, elm, attr) {
            if (attr.type === 'radio' || attr.type === 'checkbox') {
                return;
            }
            // store value when get focus
            elm.bind('focus', function () {
                scope.value = elm.val();

            });

            // execute the event when loose focus and value was change
            elm.bind('blur', function () {
                var currentValue = elm.val();
                if (scope.value !== currentValue) {
                    if (scope.myOnChange) {
                        scope.myOnChange();
                    }
                }
            });
        }
    };
});

0

Tôi đã gặp chính xác cùng một vấn đề và điều này đã làm việc cho tôi. Thêm ng-model-updateng-keyupbạn đã sẵn sàng! Đây là tài liệu

 <input type="text" name="userName"
         ng-model="user.name"
         ng-change="update()"
         ng-model-options="{ updateOn: 'blur' }"
         ng-keyup="cancel($event)" />
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.