Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Please provide option for binding ng-model for input onblur #1285

Closed

Description

@cstrong

There are certain situations where ng-model binding with onblur semantics is desirable.
For example, when input fields are used to enter dates or currency amounts.
In those cases, it is important to allow the user to finish typing the complete value before acting on it.
Of course, I can attach a custom onblur event using jQuery, but it seems reasonable to have a built-in angular API to handle this very common use case.

Activity

  1. jonbcard commented on Sep 27, 2012

    @jonbcard
    Contributor

    Having more control over the event bindings ng-model fires on can also be important for performance considerations. There are a lot of cases where I'd be happy to delay $setViewValue being called until onblur to avoid sluggishness while typing.

  2. pkozlowski-opensource commented on Nov 14, 2012

    @pkozlowski-opensource
    Member

    Duplicate of #1277

  3. sinelaw commented on Mar 7, 2013

    @sinelaw
    Contributor

    I'm not sure this is a duplicate of #1277 - this issue is about the way ngModel behaves, not about missing directives for blur/focus.

    Here's what I'm using in the meanwhile. It's based on an answer by Vojta Jína - http://jsfiddle.net/JYTUB/1/ from https://groups.google.com/forum/?fromgroups=#!topic/angular/LH0Q1A-qTVo)

    It overrides the default ngModel behavior, and forces it to $setViewValue on 'blur':

        angular.module('directives', []).directive('input', function () {
            return {
                restrict: 'E',
                require: '?ngModel',
                link: function (scope, elm, attr, ngModelCtrl) {
                    if (!ngModelCtrl) {
                        return;
                    }
    
                    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());
                        });
                    });
                }
            };
        });
    
  4. lrlopez commented on Mar 8, 2013

    @lrlopez
    Contributor

    Hmmm... I think that allowing an override in ng-model for the bound events is a very interesting feature. Also, it's easy to implement.

    Have a look into this: http://plnkr.co/edit/DNCcAT9qrYIt4Kk9zSTp?p=preview

    There is a new attribute called ng-event that allows override the event the input is bound to. In the example, I've used the blur event so it only updates the model when the focus is lost.

    Do you like this approximation? I can write down some tests and docs and prepare a PR.

    Maybe we should also allow a comma-delimited list of events instead of just a single event.

  5. lrlopez commented on Mar 8, 2013

    @lrlopez
    Contributor

    I've coded some tests and docs. Also, now it allows a comma-delimited list of events and overriding the default behavior is optional.

    Some examples:

    • <input ng-model='name' ng-update-model-on='blur, mousemove' />: Model will get updated on blur and when the mouse moves over the control.
    • <input ng-model='name' ng-update-model-on='submit, default' />: Model will get updated instantly (default behavior) on blur and also when the control is submitted.

    I didn't like ng-event. As we specify that we want update the model on blur or on mousedown, I switched over ng-update-model-on which is closer to its meaning. Is it too long?

    Anyway I'm going to commit the changes send the PR right now.

  6. florianorben commented on Mar 9, 2013

    @florianorben

    +1 nice feature.

    Proposal for an similar/additional feature - in your code you have this:

    if (!timeout) {
           timeout = $browser.defer(function() {
           listener();
           timeout = null;
       });
    }

    I think I would be nice to do something like ng-model-update-on="timout:100" (just an example), so that the model get's updated when the viewValue hasn't been changed for 100ms.
    Could be useful for scenarios where you have to enter long texts (e.g. in a textarea) and don't need the model to be updated on each individual keystroke.

    Integrating this in the code cited above, should be quite easy i guess..

    What's your opinion about this?

  7. lrlopez commented on Mar 9, 2013

    @lrlopez
    Contributor

    It's a cool idea, but I think it would be better to implement a ng-model-update-timeout attribute instead because it will get applied to any event on the list (i.e. update 100ms after blur or keydown).

    To be useful we should have a way to restart the timer every time a event gets triggered. Following your example, the model will get updated only when you have really finished typing instead of periodically getting updated very 100ms.

    Any additional ideas? I could try to get it done soon. Thank you Florian!

  8. florianorben commented on Mar 9, 2013

    @florianorben

    Agree, ng-model-update-timeout makes way more sense.
    The example provided wasn't meant to really describe the "problem", it's basically just what triggered the idea. The way it should be done, as you said, is to trigger the update X ms after the last specified (or default) event was triggered.
    To restart the timer we could use $browser.defer.cancel(timeoutId) and afterwards "restart" it with $browser.defer(fn) again, though this seems to be a lot of overhead for potentially quite a lot of timeouts being cancelled.

  9. lrlopez commented on Mar 9, 2013

    @lrlopez
    Contributor

    Done. I've extended the ng-model-update-on feature to checkboxes and radio buttons and implemented a ng-model-update-timeout on both text and checkbox inputs.

    Also, I've updated the Plunker demo, documentation and tests.

  10. florianorben commented on Mar 9, 2013

    @florianorben

    Very cool! Great work Luis! + looks fine ;)

  11. 41 remaining items

  12. added a commit that references this issue on Mar 8, 2014
    f3bd716
  13. added a commit that references this issue on Mar 8, 2014
    8c32c33
  14. added 11 commits that reference this issue on Apr 1, 2014
    d91d65d
    fff1f1c
    f9eb1d8
    9bd4aa5
    1b8f296
    640ef4a
    b879484
    c93c454
    837ce52
    747055d
    0efe039
  15. added a commit that references this issue on Apr 4, 2014
    dbe381f
  16. rasikanab commented on Oct 9, 2014

    @rasikanab

    hi, can this kind of behaviour be used in case of radio buttons? I want to validate when the the user has moved out of all the radio button options. I cant use blur as blur will validate when the user tabs from one option to another, even before the user gets an opportunity to select an option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions