Richard
Richard

Reputation: 4840

knockout.js set focus in a template

How can I use knockout.js to set focus on an element that was created by a template bound to an array?

I have an observable array bound to a table, where each row is a set of input elements to allow the array element's properties to be edited. At the bottom is an "Add" button which pushes a new element into the array, creating a new row of input fields.

What I'm trying to do is have the focus set to the first of the newly created input fields after the "Add" button has been pressed.

HTML:

<html>
  <head>
    <script src="http://cdn.jsdelivr.net/knockout/3.0.0/knockout.debug.js"></script>
  </head>
  <body>
    <table data-bind='foreach: Attributes'>
      <tr>
        <td><input type='text' data-bind='value: Name, disable: HardCoded/></td>
        <td><input type='text' data-bind='value: Description'/></td>
        <td><button data-bind="click: $parent.removeAttribute">Delete</button></td>
      </tr>
    </table>
    <button data-bind="click: addAttribute">Add attribute</button>
  </body>
</html>

Javascript:

function Attribute(id, name, description, hardcoded) {
  var self=this;
  self.AttributeID=ko.observable(id || 0);
  self.Name=name || '';
  self.Description=description || '';
  self.HardCoded=hardcoded || false;
  self.nameFocus = true;
}

function AttributeSchema(attributeArray) {
  var self=this;

  // Properties
  self.Attributes=ko.observableArray(attributeArray);

  // Operations
  self.addAttribute=function() {
    self.Attributes.push(new Attribute());
  };

  self.removeAttribute=function() {
    self.Attributes.remove(this);
  };
}

var vmSchema=new AttributeSchema(
  [
    new Attribute(5, 'FirstName', 'First Name', true),
    new Attribute(6, 'LastName', 'Last Name', true),
    new Attribute(7, 'Blah', 'Blah', false)
  ]
);

ko.applyBindings(vmSchema);

Upvotes: 11

Views: 13848

Answers (2)

79IT
79IT

Reputation: 425

I have a field where visibility is determined by a checkbox and I wanted the field to get focus as soon as it became visible. Using the default hasfocus binding meant that the field became hidden as soon as it lost focus.

To solve this I created a "oneway" hasfocus binding like this:

ko.bindingHandlers.koFocus = {
    update: function (element, valueAccessor) {
        var value = valueAccessor();
        var $element = $(element);
            if (value()) {
                $element.focus();
            }
    }
};

I then replaced:

data-bind="hasfocus: myObservable" 

with:

data-bind="koFocus: myObservable"

Problem solved

Upvotes: 4

Uladzimir Pasvistselik
Uladzimir Pasvistselik

Reputation: 3921

Currently, you have such code:

<input type='text' data-bind='value: Name, disable: HardCoded' />

You can try to add the property hasfocus: true :

<input type='text' data-bind='value: Name, disable: HardCoded, hasfocus: true' />

See: http://knockoutjs.com/documentation/hasfocus-binding.html

Upvotes: 19

Related Questions