【问题标题】:How can I access the observable in my custom binding?如何访问自定义绑定中的 observable?
【发布时间】:2016-03-03 02:33:54
【问题描述】:

我正在使用 Bootstrap 3 Datepicker 来编辑我的 observable 属性之一的日期和时间。当我创建新记录但不能编辑已创建的记录时,它工作正常。

我的自定义绑定如下

ko.bindingHandlers.datetimepicker = {
    init: function (element, valueAccessor, allBindings) {
        var options = {
            format: 'DD/MM/YYYY hh:mm A',
            locale: 'en-AU',
            sideBySide: true,
            defaultDate: ko.unwrap(valueAccessor())
        };

        ko.utils.extend(options, allBindings.dateTimePickerOptions);

        $(element).datetimepicker(options).on("dp.change", function (evntObj) {
            var observable = valueAccessor();
            if (evntObj.timeStamp !== undefined) {
                var picker = $(this).data("DateTimePicker");
                var d = picker.date();
                if (ko.isObservable(observable)) {
                    observable(d.format(options.format));
                } else {
                    valueAccessor(d.format(options.format));
                    console.log("Not observable");
                }
                console.log(observable, "\n", $(element).val());
            }
        });
    },
    update: function (element, valueAccessor) {
        var value = ko.unwrap(valueAccessor());
        $(element).datetimepicker('date', value || '');
    }
};

这是我的 ViewModel 的相关部分

var PicksViewModel = function () {
    var self = this;
    self.pick = ko.observable();
    self.newPick = {
        Title: ko.observable(),
        Sport: ko.observable(),
        MatchTime: ko.observable(),
        PublishTime: ko.observable(),
        HomeTeam: ko.observable(),
        AwayTeam: ko.observable(),
        Analysis: ko.observable(),
        PickSummary: ko.observable()
    };
}

newPickpick 用于 2 个单独的表单。一个用于创建新的,一个用于编辑现有的选择。当我将 datepicker 用于新选择时,它按预期工作,并且我没有得到显示 Not observable 的控制台日志,但是当我编辑现有选择时,observable 不会传递给绑定,因此不会得到更新我得到了控制台日志。

如何将 observable 传递给我的自定义绑定?

我正在使用以下 html 进行绑定

<form data-bind="with:pick">
    <!-- Rest of form omitted -->
    <div class="input-group date" id="editMatchTimePicker">
        <input type="text" data-bind="datetimepicker:MatchTime">
    </div>
</form>

更新
我通过绑定到单独的 observable 并使用计算的 observable 来处理 UTC 和本地时间之间的转换来修复它。

self.editMatchTime = ko.observable();
self.localMatchTime = ko.pureComputed({
    read: function () {
        self.editMatchTime(self.pick().MatchTime);
        var local = moment.utc(self.pick().MatchTime).local().format("YYYY-MM-DD[T]HH:mm:ss");
        return local;
    },
    write: function(value) {
        var utcTime = moment(value).utc();
        self.editMatchTime(utcTime);
    },
    owner: self
});

然后我的绑定变成了

<input type="text" data-bind="datetimepicker:$root.localMatchTime">

【问题讨论】:

  • 我已尝试重建您的场景,但有一些缺失的部分。在您发布的代码中,pick 是空的,很难想象其中的内容(特别是因为没有 Pick 构造函数,而 newPick 只是一个普通对象......) .请尝试将您的代码示例转换为可运行的 sn-p。
  • 另外,当与自定义绑定绑定时,您正在视图中执行各种逻辑。如果您直接绑定到MatchTime,或者绑定到其中包含所有逻辑的可写computed,这将更有意义。目前我认为你的问题在于那一点。
  • 我已经用我尝试过的方法(只是绑定到 datetimepicker:MatchTime)编辑了我的帖子,但这并没有解决问题。我添加了a gist 来展示我如何使用从 API 返回的示例数据来设置选择。 self.getPick 在我点击所有选择列表中的编辑按钮时触发。

标签: javascript knockout.js bootstrap-datetimepicker


【解决方案1】:

您没有将 observable 绑定到您的 datetimepicker,而是绑定了一个从 observable MatchTime 转换而来的值。您可以绑定MatchTime 本身并在处理程序中进行转换,或者您可以使用allBindings 参数来获取value-bound observable。如果您绑定 observable 本身,您可以将value-binding 功能滚动到您的自定义绑定处理程序中,这样您只需进行一次绑定。 (参见“简单包装器绑定”部分here。)

【讨论】:

  • 你在哪里console.log("Not observable");,让它包含observable,这样你就可以看到它得到了什么:console.log("Not observable", observable); 听起来,因为这只是现有选择的问题,所以在某些时候您正在为 MatchTime 分配一个新值,而不是设置其内容。
  • 使用控制台记录几行 console.log(observable, "\n", $(element).val());,当我将其增加 2 小时时,这给了我:2016-01-05T22:00:00 06/01/2016 12:00 AM。如您所见,输入已更新,但 observable 仅返回 MatchTime 的原始值,而不是可观察的值。
  • 让它包含 observable,这样你就可以看到它得到了什么。在某些时候,你的 observable 变得不是 observable。
  • 我最终通过为比赛时间创建另一个可观察对象来解决此问题,并使用可写的计算可观察对象来处理本地和 UTC 之间的转换。我将您标记为答案,因为您说我没有绑定到使我走上正轨的可观察对象。
【解决方案2】:

这是我用的,好像你缺少这个初始化picker.date(value);

  ko.bindingHandlers.datetimePicker = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            var options = {
                showTodayButton: true,
                format: 'DD/MM/YYYY HH:mm',
                sideBySide: true,
                locale: 'es'
            };

            ko.utils.extend(options, allBindingsAccessor().dateTimePickerOptions);
            var $el = $(element).datetimepicker(options);
            var picker = $el.data("DateTimePicker");

            picker.date(value);

            $el.on("dp.change", function (ev) {
                var observable = valueAccessor();
                if ($el.is(':focus')) {
                    // Don't update while the user is in the field...
                    // Instead, handle focus loss
                    $el.one('blur', function (ev) {
                        var dateVal = picker.date();
                        observable(dateVal);
                    });
                }
                else {
                    observable(ev.date);
                }
            });
            //handle removing an element from the dom
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                picker.destroy();
            });
        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            $(element).data("DateTimePicker").date(value);
        }
    };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多