10

我是 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/

谢谢!

4

2 回答 2

20

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

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();
    }
};

如果 observable 为真,此绑定只是将初始化和更新委托给hasfocus并负责选择元素。使用它代替hasfocus.

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

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

于 2012-09-06T10:05:03.063 回答
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);
        }
    }
};

Tl;博士:

如果您使用它并且想要满足平板电脑/智能手机的需求,那么请务必测试这是您实际期望的交互逻辑。

于 2013-10-04T13:36:41.367 回答