1

I'm trying to replicate the 2-way data-binding example on the AngularJS website.

Here's my code (in JQuery parlance for brevity):

$('#model-textbox').on('keyup', function(){
    //get value of text box
    var text_box_str = $(this).val();

    //add it to the view
    $('#view-div').html(text_box_str);
});

It works as expected, but there seems to be some kind of delay from the time the key is released, to when the text is displayed. That delay does not happen on the AngularJS website example.

I have tried a 'keydown' event variation (which takes care of the delay), but it looks like the textbox value is not updated before the .val() call (so I'm always one key press behind).

How can I achieve quick view updates using keyup, keydown, or any other method?

ObiHill
  • 11,448
  • 20
  • 86
  • 135

2 Answers2

2

Bind on input to get the immediate synchronization. https://developer.mozilla.org/en-US/docs/Web/Events/input

var $view = $('#view-div');
var ie9 = navigator.appVersion.indexOf("MSIE 9.")!=-1;
var event = ('oninput' in document.documentElement && !ie9) && 'input' || 'keypress';

$('#model-textbox').on(event, function(){
    var $el = $(this);
    if(event === 'keypress') {
      setTimeout(function(){ $view.text($el.val()); },0);
    } else {
      $view.text($el.val());
    }
});

Also, checkout out RivetsJS for a small library that supports this functionality outside of Angular. http://rivetsjs.com

Edit: Added event support check to take you back past IE9 (if you care about such things.)

David Boskovic
  • 1,469
  • 9
  • 14
  • even IE9 has caveats .. forget exactly what they are but I think it ignores backspace – charlietfl Oct 20 '15 at 19:25
  • Yeah, added a note regarding that. A browser detection method would be appropriate and then just use `input keyup` as the event. You get double-execution but, that's a fair compromise. – David Boskovic Oct 20 '15 at 19:36
  • @dboskovic Thanks. I tried `.on('input keyup')` and it works great! Will test on the IE browsers and tweak as needed. Is there a major difference between that and your code? – ObiHill Oct 20 '15 at 19:51
  • @ObinwanneHill I edited my answer and added full crossbrowser support. You should be good now. – David Boskovic Oct 20 '15 at 19:57
  • @dboskovic Thanks. I tried `.on('input keyup')` on IE8 and IE9 and it works when adding characters. However I notice the delay on both for backspace (on account of the input bug [for IE9] / fallback to keyup), which I can live with. I'm actually using a custom .on method that has a fallback to `onpropertychange` for IE8. Cheers. – ObiHill Oct 20 '15 at 21:47
  • @ObinwanneHill yeah, the backspace delay in IE9 could be resolved if you *really* cared. Check the keypress keycode for the backspace / delete keycode and pre-delete the last symbol. – David Boskovic Oct 20 '15 at 21:57
  • Also this comment has an interesting idea: http://stackoverflow.com/a/3463547/2528925. By catching keypress, but then doing a 0ms timeout before checking the value. Definitely weightier, but probably a better experience fallback for the older browsers. – David Boskovic Oct 20 '15 at 21:59
  • I updated my answer to use the `setTimeout` approach. I like it better. Now you should have instant updates for new *and* old browsers. @ObinwanneHill – David Boskovic Oct 20 '15 at 22:07
  • @DavidBoskovic Thanks a lot for helping out with this. I was going to settle with `input keyup` but this has got me pushing further. Cheers. – ObiHill Oct 23 '15 at 00:16
  • @DavidBoskovic `keypress` doesn't seem work on IE9, so I used `keydown` instead and it seems to be working ok so far. Could you verify and update answer? – ObiHill Oct 24 '15 at 15:00
0

I don't see that much of a delay, but it may help if you cache the jquery objects (the bigger the DOM, the more this will help):

var $view = $('#view-div');
var $box = $('#model-textbox');
$box.on('keyup', function(){
    //get value of text box
    var text_box_str = $box.val();

    //add it to the view
    $view.html(text_box_str);
});

https://jsbin.com/ruxajowolo/edit?html,js,output

spmurrayzzz
  • 136
  • 2
  • definitely help...doesn't require a dom search for each keystroke. The `$box` won't make any difference though ... `$view` will. `this.value` even more efficient than using jQuery – charlietfl Oct 20 '15 at 18:45
  • The issue she's experiencing is solved by binding to the `input` event. – David Boskovic Oct 20 '15 at 18:54
  • @dboskovic careful though , event not supported in older browsers http://caniuse.com/#search=input – charlietfl Oct 20 '15 at 19:02
  • @dboskovic given that its support isn't universal, I tend to avoid using it — unless I have built-in feature detection – spmurrayzzz Oct 20 '15 at 19:05
  • @charlietfl good point. I don't usually think about support further than IE9 anymore. But added a condition to my example. You could also monitor both events, I suppose. – David Boskovic Oct 20 '15 at 19:22
  • @spmurrayzzz It's a slight delay, not very noticeable, but the angularjs.org example is instant. Tried this and I still get the same effect – ObiHill Oct 20 '15 at 19:42