使用Knockout.js选择()输入字段

时间:2012-09-06 07:19:19

标签: select input knockout.js focus viewmodel

我是Knockout.js的新手。

select() <input />变为可见时,最佳方式是什么?

查看:

<p>
    Name: 
    <b data-bind="visible: !editing(), text: name, click: edit">&nbsp;</b>
    <input data-bind="visible: editing, value: name, hasfocus: editing" />
</p>

视图模型:

function PersonViewModel(name) {
    // Data
    this.name = ko.observable(name);
    this.editing = ko.observable(false);

    // Behaviors
    this.edit = function() { this.editing(true) }
}

ko.applyBindings(new PersonViewModel("Bert Bertington"));

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

http://jsfiddle.net/RnCUd/

谢谢!

2 个答案:

答案 0 :(得分:19)

您可以创建一个新的绑定来处理选择。

ko.bindingHandlers.selected = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var selected = ko.utils.unwrapObservable(valueAccessor());
        if (selected) element.select();
    }
};

将此绑定添加到输入字段。

<input data-bind="visible: editing, value: name, hasfocus: editing, selected: editing" />

这是一个小提琴:http://jsfiddle.net/RnCUd/2/


或者,您可以创建一个包装hasfocus绑定的自定义绑定:

ko.bindingHandlers.hasSelectedFocus = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ko.bindingHandlers['hasfocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
    },        
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ko.bindingHandlers['hasfocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);        

        var selected = ko.utils.unwrapObservable(valueAccessor());
        if (selected) element.select();
    }
};

此绑定只是将初始化和更新委托给hasfocus,如果observable为true,则负责选择元素。使用它而不是hasfocus

<input data-bind="visible: editing, value: name, hasSelectedFocus: editing" />

这是一个小提琴:http://jsfiddle.net/RnCUd/1/

答案 1 :(得分:1)

我尝试在上面使用John Earles自定义绑定(感谢John!)以及一个也使用了valueUpdate的文本字段:'afterkeydown'绑定并发现它并没有按预期工作。 (我猜这是因为当其中一个绑定需要触发时,所有绑定都会再次触发,而valueUpdate很可能导致在每个字符写入后触发值绑定)。

经过几次尝试,我为这个问题做了一个半修复,似乎对我有用。基本的想法是,在我们触发hasfocus绑定之前,我们检查所讨论的元素是否已经具有焦点,并且我们实际上只在元素在hasfocus绑定被触发之前没有实际焦点时选择文本。

我使用jquery来检查焦点,但你也可以用其他方式来做。

ko.bindingHandlers.hasSelectedFocus = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ko.bindingHandlers['hasfocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var focusBefore = $(element).is(':focus');
        ko.bindingHandlers['hasfocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);

        var selected = ko.utils.unwrapObservable(valueAccessor());
        if (selected && !focusBefore) {
            element.select();   
        }
    }
};

编辑:我注意到这种绑定在iOS设备上使用时可能无法正常工作。这样的绑定没有任何问题,但是自动对焦和选择逻辑会导致设备键盘在绑定执行后立即出现,这可能与您想要在这样的设备上发生的情况完全相同。比较一下,在我用来测试的android设备上,一旦执行此绑定,我就不会自动获取键盘。为了我的缘故,我最终创建了另一个绑定,以便通过以下方式在iOS设备上执行任何操作。

ko.bindingHandlers.hasNonIosSelectedFocus = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        if (navigator.userAgent.match(/iPad/i) == null && navigator.platform.indexOf("iPhone") == -1 && navigator.platform.indexOf("iPod") == -1) {
            ko.bindingHandlers['hasSelectedFocus'].init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
        }
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        if (navigator.userAgent.match(/iPad/i) == null && navigator.platform.indexOf("iPhone") == -1 && navigator.platform.indexOf("iPod") == -1) {
            ko.bindingHandlers['hasSelectedFocus'].update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext);
        }
    }
};

铊; DR:

如果你使用它并想要迎合平板电脑/智能手机,那么一定要测试这是你实际期望的交互逻辑。