我有自己的淘汰赛组件:

ko.components.register("library-link-form",
{
  viewmodel: LibraryLinkViewModel,
  template: { controller: "PartialViews", action: "LibraryLinkPartial" }
  //This is custom template loader, which loads asp.net partial view from controller via ajax request.
});


我的LibraryLinkViewModel.js

function LibraryLinkViewModel() {
  var self = this;

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

  self.Type = ko.observable("");
}


局部视图_LibraryLinkForm

@{
    var libraryDropdownId = $"dropdown-{Guid.NewGuid().ToString().Substring(0, 8)}";
    var typeDropdownId = $"dropdown-{Guid.NewGuid().ToString().Substring(0, 8)}";
    var scriptId = $"script-{Guid.NewGuid().ToString().Substring(0, 8)}";
    var contextId = $"context-{Guid.NewGuid().ToString().Substring(0, 8)}";
    var librariesList = //some list with predefined libraries
    var typeList = // some list with predefined library's types
}
<!-- ko template: { afterRender: function()
{
eval($('#@scriptId').html());
}
}
-->
<!-- /ko -->
<div id ="@contextId">
  <div class="row">
    <div class="col-md-12">
      <div class="panel panel-default">
        <div class="panel-body">
          <div class="col-md-12">
            <div class="row">
              <form class="form-horizontal">
                <div class="form-group">
                  <div class="col-md-6">
                    @(Html.Kendo().DropDownList()
                      .Name(libraryDropdownId)
                      .DataValueField("Value").DataTextField("Text")
                      .HtmlAttributes(new
                      {
                        style = "width: 100%",
                        data_bind = "value: OtherLibrary"
                      }).BindTo(librariesList).Deferred()
                    )
                  </div>
                  <div class="col-md-4">
                    @(Html.Kendo().DropDownList()
                        .Name(typeDropdownId)
                        .DataValueField("Value").DataTextField("Text")
                        .HtmlAttributes(new
                        {
                          style = "width: 100%",
                          data_bind = "value: Type"
                        }).BindTo(typeList).Deferred()
                        )
                  </div>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <deferred-script class="hidden" id="@scriptId">
    @(Html.Kendo().DeferredScripts(false))
  </deferred-script>
</div>


最后,我如何结合所有这些:

<button type="button" data-bind="click: addLibraryLink"></button>
<ul class="list-unstyled" data-bind="foreach: LibraryLinks">
    <li><library-link-form></library-link-form></li>
</ul>
<script type="text/javascript">
    function LibraryViewModel() {
        var self = this;
        self.LibraryLinks = ko.observableArray();
        self.addLibraryLink = function () {
            ko.components.clearCachedDefinition();
            self.LibraryLinks.push(new LibraryLinkViewModel());
       };
    }
    ko.applyBindings(new LibraryViewModel());
</script>


我正在使用Knockout v.3.4,Asp.Net Core v.1.0.0。

因此,问题在于,当我尝试将新的库链接添加到列表时,敲除绑定根本无法正常工作,可能是因为错误:


  未捕获ReferenceError:无法处理绑定“值:功能
  (){return OtherLibrary}“消息:未定义OtherLibrary


我应该怎么处理这个错误?如何正确将淘汰赛的组件添加到列表中?

最佳答案

答案很简单。让我们看一下示例,并检查其中的上下文:

<div data-bind="foreach: LibraryLinks"> // here we have LibraryViewModel context
    <library-link-form> // here we have LibraryLinkViewModel context
        //inside component we have THIRD context, which is empty!
    </library-link-form>
</div>


因此,问题在于,data_bind = "value: OtherLibrary"中的OtherLibrary引用了第三个上下文,该上下文为空且未定义。

只需调用父母的上下文即可解决问题。

例如:data_bind = "value: $parent.OtherLibrary"

10-07 23:00