Angularjs: введення [текст] ngChange спрацьовує під час зміни значення


92

ngChange спрацьовує, коли значення змінюється (ngChange не є подібним до класичної події onChange). Як я можу прив'язати класичну подію onChange за допомогою angularjs, яка запускатиметься лише тоді, коли вміст буде зафіксовано?

Поточне прив'язка:

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

Просто шукаючи щось подібне, і мені здалося, що ви також можете розглянути можливість оновлення лише тоді, коли поле дійсне. Таким чином користувач може боротися з тим, щоб ввести дані у дійсний формат (або ви можете допомогти їм підказками та фільтрами), тоді ви зможете винагородити їх оновленням, коли вони все зрозуміють!
Steve Black

Набагато більш гнучке рішення, яке дозволяє вказати подію для використання (а не просто розмиття) та інші властивості, має бути вбудовано в angular
wired_in

Відповіді:


96

Цей пост показує приклад директиви, яка затримує зміни моделі на вхідні дані, доки не спрацює подія розмиття .

Ось скрипка, в якій показано, як ng-change працює з новою директивою ng-model-on-blur. Зверніть увагу, що це невелика корекція оригінальної скрипки .

Якщо ви додасте директиву до свого коду, ви зміните прив'язку до цього:

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

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

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

Примітка: як згадує @wjin у коментарях нижче, ця функція підтримується безпосередньо в Angular 1.3 (на даний момент у бета-версії) через ngModelOptions. Докладнішу інформацію див. У документації .


1
Обережно, elm.unbind ('input') видає 'TypeError' у Internet Explorer 8, тому інші оператори unbind не будуть виконуватися взагалі. Я вирішив це, перемістивши elm.unbind ('input') в окремий рядок і оточив його блоком try / catch.
Роб Юрлінк,

1
Angular 1.2 має ng-blurдирективу: docs.angularjs.org/api/ng.directive:ngBlur
JJ Zabkar

5
Я змусив цей код працювати, але мені довелося встановити пріоритет директиви (тобто пріоритет: 100). Я використовую Angular 1.2.10. Я припускаю, що директива ngModelOnblur працювала до директиви ngModel, тож відв’язувати ще не було чого. Крім того, на цій сторінці здається, що в майбутньому для цього може бути вбудоване рішення: github.com/angular/angular.js/pull/1783
Алан Вест

4
ПРИМІТКА Принаймні в кутовій ng-model-options="{ updateOn: 'default blur' }"
версії

2
@RobJuurlink (або будь-хто інший, хто стикається з IE8 'TypeError' при спробі прив'язати або відв'язати до 'input') - Переглядаючи джерело Angular, ви побачите, що вони використовують $snifferдля визначення, підтримує браузер "input", а якщо ні, вони повертаються до "клавіатури". Якщо ви оновите вищевказану директиву лише для того, щоб розв'язати 'input', лише якщо $sniffer.hasEvent('input')повертає true - тоді ви можете уникнути цієї помилки і все одно працювати в IE8
bvaughn

32

Мова йде про нещодавні доповнення до AngularJS, які слугуватимуть майбутньою відповіддю (також на інше питання ).

Нові версії Angular (тепер у версії 1.3 бета-версії), AngularJS спочатку підтримує цю опцію, використовуючи ngModelOptions, як

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

Документи NgModelOptions

Приклад:

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

Це не працює коректно в 1.3 бета-версії 5, але виправлено в поточній майстер-версії 2602
manikanta

І тому він все ще знаходиться в бета-версії і не використовується в «реальних» додатках, таких як той, який я будую зараз.
reaper_unique

Ось параметри ng-model, такі як модуль для Angular 1.2.x github.com/fergaldoyle/modelOptions
Фергал

8

Якщо хтось ще шукає додаткову підтримку натискання клавіш "enter", ось оновлення скрипки, надане Gloppy

Код для прив'язки натискання клавіші:

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

5

Для тих, хто бореться з IE8 (йому не подобається відв’язувати („введення”), я знайшов спосіб обійти його.

Введіть $ sniffer у свою директиву та використовуйте:

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

IE8 заспокоюється, якщо це зробити :)


або просто використовуйте try / catch
wired_в

4

Наскільки я знаю, ми повинні використовувати ng-change із параметром select, а у випадку з текстовим полем - ng-blur.


Це правильна відповідь зараз, тоді, коли було задано питання, воно, очевидно, не існувало.
виїзд

Щиро дякую ... це мала б бути відповідь
Ренджіт

3

Не використовує $ scope. $ Watch, щоб краще відображати зміни змінної сфери?


1
Їжа для роздумів: benlesh.com/2013/10/title.html (з назвою: ви, мабуть, не повинні використовувати $ watch у своїх контролерах)
BenB

0

Замінити введення за замовчуванням поведінку onChange (викликати функцію лише тоді, коли змінено фокус і значення втрати контролю)

Примітка: ngChange не схожий на класичне подія OnChange його стрілянину події в той час як значення змінюється Цією директива зберігає значення елемента , коли він отримує фокус
на розмиває він перевіряє , чи змінилося нове значення , і якщо так , то спрацьовує подія

@param {Рядок} - ім'я функції, яке буде викликано, коли має бути запущено "onChange"

@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

У мене була точно така ж проблема, і це спрацювало для мене. Додайте ng-model-updateі ng-keyupі готово! Ось документи

 <input type="text" name="userName"
         ng-model="user.name"
         ng-change="update()"
         ng-model-options="{ updateOn: 'blur' }"
         ng-keyup="cancel($event)" />
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.