如何在knockout“with:”上下文中解决ReferenceError

时间:2014-01-17 15:59:13

标签: javascript jquery knockout.js

以下行有什么问题?

 <div id="dialog" data-bind="with: SelectedText, dialog: {'autoOpen': false, 'title': textbatchTitle }, dialogVisible: $root.isMetadataDialogOpen "></div>

我收到控制台错误:“ReferenceError:textbatchTitle未定义”

同时在页面的早些时候,这个工作正常:

<div id="Div1" class="textbatchdetails" data-bind="with: SelectedText" >
     <div>  
         <input type="text" name="textbatchTitle" data-bind="value: textbatchTitle, valueUpdate: 'afterkeydown'"  />
     </div>

我的对话框绑定如下所示:

ko.bindingHandlers.dialog = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var options = ko.utils.unwrapObservable(valueAccessor()) || {};

        //do in a setTimeout, so the applyBindings doesn't bind twice from element being copied and moved to bottom
        setTimeout(function () {
            options.close = function () {
                allBindingsAccessor().dialogVisible(false);
            };

            $(element).dialog(ko.toJS(options));
        }, 0);

        //handle disposal (not strictly necessary in this scenario)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).dialog("destroy");
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().dialogVisible),
            $el = $(element),
            dialog = $el.data("uiDialog") || $el.data("dialog"),
            options = valueAccessor();

        //don't call dialog methods before initilization
        if (dialog) {
            $el.dialog(shouldBeOpen ? "open" : "close");

            for (var key in options) {
                if (ko.isObservable(options[key])) {
                    $el.dialog("option", key, options[key]());
                }
            }
        }
    }
};

1 个答案:

答案 0 :(得分:0)

Eric Brenden基本上给了你答案:

<div id="dialog" data-bind="with: SelectedText, dialog: {'autoOpen': false, 'title': textbatchTitle }, dialogVisible: $root.isMetadataDialogOpen ">
    <!-- INSIDE here, 'SelectedText' is the binding context, and 'textbatchTitle' works. However, the div with id = "dialog" ITSELF does not yet have the binding context 'SelectedText', instead its context is the parent of 'SelectedText'
</div>

对比:

<div id="Div1" class="textbatchdetails" data-bind="with: SelectedText" >
     <!-- In here, just like above, the binding context is 'SelectedText'. So on this level, 'textbatchTitle' is fine
     <div>  
         <input type="text" name="textbatchTitle" data-bind="value: textbatchTitle, valueUpdate: 'afterkeydown'"  />
     </div>
</div>

解决方案1:

<div data-bind="with: SelectedText">
    <div id="dialog" data-bind="dialog: {'autoOpen': false, 'title': textbatchTitle }, dialogVisible: $root.isMetadataDialogOpen "></div>
</div>

解决方案2 :( SelectedText不可观察)

    <div id="dialog" data-bind="with: SelectedText, dialog: {'autoOpen': false, 'title': SelectedText.textbatchTitle }, dialogVisible: $root.isMetadataDialogOpen ">

解决方案3 :( SelectedText observable)

    <div id="dialog" data-bind="with: SelectedText, dialog: {'autoOpen': false, 'title': SelectedText() ? SelectedText().textbatchTitle : '' }, dialogVisible: $root.isMetadataDialogOpen ">

还有其他方法可以解决这个问题(例如计算出的可观测量) 我会去解决方案1。