Search code examples
backbone.js

Backbone: Lost input focus after view re-render


I have a form with several input fields. When changing values in inputs, view with form is re-rendering. Here is some piece of Backbone.View code:

initialize: ->
    @model.on('change', @render, @)

events:
    'change input': 'change'

change: (event) ->
    ctrl  = @$(event.currentTarget)
    @model.set(ctrl.data('name'), ctrl.val())

render: ->
    @$el.html(@template(@model.toJSON()))

But re-rendering occurs also when I press tab key to set focus in next input and focus is lost. Is it possible to solve this problem with a little portion of code?


Solution

  • Currently you're (in essence) re-rendering the whole form every time anything changes. Ideally a better way to go would be to have different views for the different parts of the form, and only re-render the parts that actually need to be render-ed, based on the specifics of what changed.

    But that doesn't really help if you're looking for:

    is it possible to solve this problem with a little portion of code?

    So here's a different approach you can try: modify your render to do something like:

    render: ->
        focusedElementId = $(':focus').attr('id');
        @$el.html(@template(@model.toJSON()))
        $('#' + focusedElementId).focus();
    

    In other words, on every render store which element is focused (or rather, its ID, since that element will go away as part of your rendering), and then restore that focus after the render.

    Of course, this assumes that all of the elements involved have IDs. If they don't, you'll either need to add IDs to them or find some other way to keep track of which element was focused. For example, you could do something like var focusedIndex = $('input').index();, but don't use that literally without testing first to ensure that the index stays consistent, because it might not be (if say the number or order of inputs on the page changes).