首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >formatter.js重写敲除值

formatter.js重写敲除值
EN

Stack Overflow用户
提问于 2016-08-25 07:50:19
回答 1查看 185关注 0票数 0

我使用knockout.js来绑定要查看的值。当显示模态时,我初始化格式化程序。这是样本:

代码语言:javascript
运行
复制
<input type="text" id="propertyName" class="form-control" name="name" required="" data-bind="value: Name">

$("#exampleFormModal").on("shown.bs.modal", function () {
        self.InitFormatter();
    });

    self.InitFormatter = function () {
        $('#propertyName').formatter({
           'pattern': '{{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}}',
           'persistent': true
        });
    }

问题是value: Name中存在空值。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-27 11:10:24

使用对任何类型的DOM操作--包括元素上的值更新--进行删除的库需要一个自定义绑定处理程序,这样敲除就可以( a)正确地初始化该库,b)在视图模型和视图之间传递任何更新。

为formatter.js编写自定义绑定处理程序很棘手,因为formatter.js非常严格地控制在输入元素上发生的所有与值相关的事件(键盘、粘贴),而不暴露自己的任何事件。

换句话说,设置起来很容易,但是很难在值更改时得到通知。但这正是保持视图模型更新所必需的。

为了能够做到这一点,我们必须连接到格式化程序的内部功能之一-- 方法。每当输入的值发生变化时,都会调用此方法,因此它是设置一个小的“告密者”的最佳位置,当值发生变化时,它会通知剔除。

免责声明这是一次黑客攻击。只要formatter.js内部发生变化,它就会崩溃。然而,在当前的0.1.5版本中,它似乎运行得相当好。

这样我们就可以这样把我们的观点捆绑起来:

代码语言:javascript
运行
复制
<input data-bind="formatter: {
    value: someObservable,
    pattern: '{{9999}}-{{9999}},
    persistent: true
}">

someObservable更改时,敲除可以填充输入值,而且由于_processKey的钩子,它还可以在输入值更改时更新someObservable

绑定处理程序的完整实现如下(它不依赖jQuery ):

代码语言:javascript
运行
复制
// ko-formatter.js
/* global ko, Formatter */

ko.bindingHandlers.formatter = {
    init: function (element, valueAccessor) {
        var options = ko.unwrap(valueAccessor()) || {},
            instance = new Formatter(element, ko.toJS(options)),
            _processKey = Formatter.prototype._processKey,
            valueSubs, patternSubs, patternsSubs;

        if (ko.isWritableObservable(options.value)) {
            // capture initial element value
            options.value(element.value);
            // shadow the internal _processKey method so we see value changes
            instance._processKey = function () {
                _processKey.apply(this, arguments);
                options.value(element.value);
            };
            // catch the 'cut' event that formatter.js originally ignores
            ko.utils.registerEventHandler(element, 'input', function () {
                options.value(element.value);
            });
            // subscribe to options.value to achieve two-way binding
            valueSubs = options.value.subscribe(function (newValue) {
                // back out if observable and element values are equal
                if (newValue === element.value) return;
                // otherwise reset element and "type in" new observable value
                element.value = '';
                _processKey.call(instance, newValue, false, true);
                // write formatted value back into observable
                if (element.value !== newValue) options.value(element.value);
            });
        }
        // support updating "pattern" option through knockout
        if (ko.isObservable(options.pattern)) {
            patternSubs = options.pattern.subscribe(function (newPattern) {
                instance.resetPattern(newPattern);
            });
        }
        // support updating "patterns" option through knockout
        if (ko.isObservable(options.patterns)) {
            patternsSubs = options.patterns.subscribe(function (newPatterns) {
                instance.opts.patterns = newPatterns;
                instance.resetPattern();
            });
        }
        // clean up after ourselves
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            if (valueSubs) valueSubs.dispose();
            if (patternSubs) patternSubs.dispose();
            if (patternsSubs) patternsSubs.dispose();
        });
    }
    // this binding has no "update" part, it's not necessary
};

这还支持使pattern可以被观察到,因此您可以动态地更改输入字段的模式。

现场演示(展开以运行):

代码语言:javascript
运行
复制
// ko-formatter.js
/* global ko, Formatter */

ko.bindingHandlers.formatter = {
    init: function (element, valueAccessor) {
        var options = ko.unwrap(valueAccessor()) || {},
            instance = new Formatter(element, ko.toJS(options)),
            _processKey = Formatter.prototype._processKey,
            valueSubs, patternSubs, patternsSubs;

        if (ko.isWritableObservable(options.value)) {
            // capture initial element value
            options.value(element.value);
            // shadow the internal _processKey method so we see value changes
            instance._processKey = function () {
                _processKey.apply(this, arguments);
                options.value(element.value);
            };
            // catch the 'cut' event that formatter.js originally ignores
            ko.utils.registerEventHandler(element, 'input', function () {
                options.value(element.value);
            });
            // subscribe to options.value to achieve two-way binding
            valueSubs = options.value.subscribe(function (newValue) {
                // back out if observable and element values are equal
                if (newValue === element.value) return;
                // otherwise reset element and "type" new observable value
                element.value = '';
                _processKey.call(instance, newValue, false, true);
                // write formatted value back into observable
                if (element.value !== newValue) options.value(element.value);
            });
        }
        // support updating "pattern" option through knockout
        if (ko.isObservable(options.pattern)) {
            patternSubs = options.pattern.subscribe(function (newPattern) {
                instance.resetPattern(newPattern);
            });
        }
        // support updating "patterns" option through knockout
        if (ko.isObservable(options.patterns)) {
            patternsSubs = options.patterns.subscribe(function (newPatterns) {
                instance.opts.patterns = newPatterns;
                instance.resetPattern();
            });
        }
        // clean up after ourselves
        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            if (valueSubs) valueSubs.dispose();
            if (patternSubs) patternSubs.dispose();
            if (patternsSubs) patternsSubs.dispose();
        });
    }
    // this binding has no "update" part, it's not necessary
};

// viewmodel implementation

ko.applyBindings({
    inputPattern: ko.observable('{{9999}}-{{9999}}-{{9999}}-{{9999}}'),
    inputValue: ko.observable(),
    setValidValue: function () {
        var dummy = this.inputPattern().replace(/\{\{([a9*]+)\}\}/g, function ($0, $1) {
            return $1.replace(/\*/g, "x");
        });
        this.inputValue(dummy);
    },
    setInvalidValue: function () {
        this.inputValue('invalid value');
    }
});
代码语言:javascript
运行
复制
input {
    width: 20em;
}
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/formatter.js/0.1.5/formatter.min.js"></script>

View:<br>
<input data-bind="formatter: {
    value: inputValue,
    pattern: inputPattern,
    persistent: true
}">
<input data-bind="value: inputPattern"><br>
<button data-bind="click: setValidValue">Set valid value</button>
<button data-bind="click: setInvalidValue">Set invalid value</button>

<hr>
Viewmodel:<br>
<pre data-bind="text: ko.toJSON($root, null ,2)"></pre>

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39139555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档