0

我有以下代码,我试图使用可写的计算 observable 来验证用户输入,并自动拒绝无效输入。这只是一些测试代码,我试图阻止用户从文本中删除逗号字符。如果用户删除逗号字符,我会尝试将编辑器重新绑定到先前的值以覆盖最近的更改。这可能使用可写计算域吗?我遇到的问题是,可写计算绑定仅在我加载页面时触发(在手动设置 ValidText 属性之后)。但是,当用户在编辑器中键入内容时,我无法触发它。

代码:

<script type="text/javascript">

    var model = null;

    function EditModel() {

        this.Count = 2;

        var self = this;

        this.ExistingValue = ko.observable("");

        this.ValidText = ko.computed({
            read: function () {
                return self.ExistingValue();
            },
            write: function (text) {
                if (text.split(',').length === self.Count) {
                    self.ExistingValue(text);
                }
            },
            owner: self
        });
    }

    $(document).ready(function () {

        model = new EditModel();

        model.ValidText('@(Model.Text)');

        ko.applyBindings(model);
    });

</script>

<div id="mainContainer">
    <div id="editor" contenteditable="true" class="commentEditBox" data-bind="text: ValidText, valueUpdate: 'afterkeydown'" ></div>
</div> 

最终采用自定义绑定的想法并将代码转换为以下内容:

<script type="text/javascript">

    var model = null;

    ko.bindingHandlers.customEditorBinding = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

            $(element).on('keydown', function () {
                var observable = valueAccessor();
                observable($(this).text());
            });
        },
        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            var text = ko.utils.unwrapObservable(valueAccessor());

            if (text.split(',').length === model.Count) {
                model.ValidText(text);
                model.PreviousText = text;
                $(element).text(text);
            }
            else {
                 model.ValidText(model.PreviousText);
                $(element).text(model.PreviousText);
            }
        }
    };

    function EditModel() {

        var self = this;

        self.Count = 2;

        self.ValidText = ko.observable("");

        self.PreviousText = null;
    }

    $(document).ready(function () {

        model = new EditModel();

        model.ValidText('This is,a test');

        ko.applyBindings(model);
    });

</script>

<div id="mainContainer">
    <div id="editor" contenteditable="true" class="commentEditBox" data-bind="customEditorBinding:ValidText" ></div>
</div>
4

2 回答 2

1

好的,混淆了 self 和 this 的使用,你已经使用文本将它绑定到一个 div,并且你试图让它在值发生变化时更新。该 html 元素没有任何价值,所以这就是它没有触发的原因。

查看自定义绑定并将您的写入逻辑移动到它的更新方法中。

ko.bindingHandlers.yourBindingName = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // This will be called when the binding is first applied to an element
        // Set up any initial state, event handlers, etc. here
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // This will be called once when the binding is first applied to an element,
        // and again whenever the associated observable changes value.
        // Update the DOM element based on the supplied values here.
    }
};
于 2013-03-08T16:04:05.910 回答
0

在你的 write 方法中,添加这个 else 子句:

else { self.ValidText.notifySubscribers(self.ExistingValue()); }

这将强制文本框更新回原始值。

于 2013-03-08T16:04:24.773 回答