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.