How to set focus of input after computed has been updated

315 views Asked by At

I have table/grid that shows devices based on their type. Whenever the dropdown changes, the table should update to show the correct devices. To do this i have a computed that filters the devices by type and adds a new blank row to the table/grid.

Here's the html:

<table>
    <thead>
        <tr>
            <th><!--Row Number--></th>
            <th>Serial No.</th>
            <th>Name</th>
            <th><!--Delete Button--></th>
        </tr>
    </thead>
    <tbody data-bind="foreach: filteredDevices">
        <tr>
            <td data-bind="text: $index() + 1"></td>
            <td><input data-bind="value: serial, event: { change: ($parent.filteredDevices().length == $index() + 1) ? $parent.addDevice : '' }" /></td>
            <td><input data-bind="value: name, event: { change: ($parent.filteredDevices().length == $index() + 1) ? $parent.addDevice : '' }" /></td>
            <td><button type="button" data-bind="visible: $parent.filteredDevices().length != $index() + 1, click: $parent.deleteDevice">Delete</button></td>
        </tr>
    </tbody>
</table>

Knockout code:

var DevicesViewModel = function () {
    var self = this;

    self.devices = ko.observableArray([{ name: 'test1', serial: 'test1', type: 'type1' },{ name: 'test2', serial: 'test2', type: 'type2' }]);
    self.selectedDeviceType = ko.observable("type1");

    self.deviceTypes = ko.observableArray([
        { value: 'type1', name: 'Type 1' },
        { value: 'type2', name: 'Type 2' }
    ]);

    self.addDevice = function (data) {
        self.devices.push({ name: data.name, serial: data.serial, type: data.type });
    };

    self.deleteDevice = function (device) {
        self.devices.remove(device);
    };

    self.filteredDevices = ko.computed(function () {
        var arr = ko.utils.arrayFilter(self.devices(), function (device) {
            return device.type == self.selectedDeviceType();
        });

        arr.push({ name: null, serial: null, type: self.selectedDeviceType() });

        return arr;
    });
};

ko.applyBindings(new DevicesViewModel());

Here is the fiddle for it: https://jsfiddle.net/wa9108bf/

If you tab through the grid initially, everything works fine. However if you type something into the first input of the last row and tab over, the focus gets lost. I'm guessing this happens because the computed is updated and the table is rendered again with the new computed array which know nothing about the focus. Is there a way to get the functionality I want?

1

There are 1 answers

0
Michael Best On BEST ANSWER

The input will lose focus because you're removing the current item and adding a copy. If you instead maintain the current item in the array, the focus will remain.

Change

self.addDevice = function (data) {
    self.devices.push({ name: data.name, serial: data.serial });
};

to

self.addDevice = function (data) {
    self.devices.push(data);
};