使用无容器控制流语法的Knockout错误

时间:2017-11-20 10:37:33

标签: javascript jquery knockout.js

我还是新人淘汰赛,所以也许我做错了什么。我有一个带动态输入控件的html表单,可以由用户添加。我不知道问题是否是由无容器控制流语法引起的,但我不知道如果没有它我将如何实现相同的结果。

动态部分的标记是:

  //begin form

  <!-- ko foreach: durationValues -->
      <div class="form-group">
          <!-- ko if: ($index() === 0) -->
              <label for="Values[0].Value">Values</label>
          <!-- /ko -->
          <div class="input-group">
              <input class="form-control" type="text" data-bind="value: text, attr: { name: 'Values[' + $index() + '].Value' }" data-val="true" data-val-required="Value required." />
              <span class="input-group-btn">
                  <!-- ko if: ($index() === 0) -->
                      <button class="btn btn-outline-secondary" type="button" data-bind="click: addDurationValue"><i class="fa fa-plus-circle"></i> Add</button>
                  <!-- /ko -->
                  <!-- ko if: ($index() > 0)-->
                      <button class="btn btn-outline-secondary" type="button" data-bind="click: $parent.removeDurationValue"><i class="fa fa-trash"></i> Remove</button>
                  <!-- /ko -->
              </span>
          </div>
          <span class="field-validation-valid invalid-feedback" data-bind="attr: { 'data-valmsg-for': 'Values[' + $index() + '].Value' }" data-valmsg-replace="true"></span>
      </div>
  <!-- /ko -->

  //endform
  //jquery, jquery-validate, jquery-validate-unobtrusive, bootstrap and knockout script files loaded

  <script>
  function DurationValue(text) {
        this.text = text;
    }

    function DurationValuesViewModel() {
        var self = this;

        self.durationValues = ko.observableArray([
            new DurationValue("")
        ]);

        self.addDurationValue = function () {
            self.durationValues.push(new DurationValue(""));

            //Remove current form validation information
            $("form")
                .removeData("validator")
                .removeData("unobtrusiveValidation");

            //Parse the form again
            $.validator.unobtrusive.parse("form");
        };

        self.removeDurationValue = function (durationValue) { self.durationValues.remove(durationValue); };
    }

    ko.applyBindings(new DurationValuesViewModel());
  </script>

页面一直在喊我这些错误:

  

未捕获的ReferenceError:

     

无法处理绑定&#34; foreach:function(){return durationValues}&#34;

     

消息:无法处理绑定&#34; if:function(){return($ index()=== 0)}&#34;

     

消息:无法处理绑定&#34;点击:function(){return addDurationValue}&#34;

     

消息:未定义addDurationValue       at click(eval at createBindingsStringEvaluator(knockout-3.4.2.debug.js:2992),:3:58)       在newValueAccessor(knockout-3.4.2.debug.js:4231)       在init(knockout-3.4.2.debug.js:4241)       在init(knockout-3.4.2.debug.js:4234)       在knockout-3.4.2.debug.js:3368       at Object.ignore(knockout-3.4.2.debug.js:1480)       在knockout-3.4.2.debug.js:3367       at Object.arrayForEach(knockout-3.4.2.debug.js:159)       at applyBindingsToNodeInternal(knockout-3.4.2.debug.js:3353)       at applyBindingsToNodeAndDescendantsInternal(knockout-3.4.2.debug.js:3233)

1 个答案:

答案 0 :(得分:2)

您的无容器控制流语法很好。但是,您需要在$parent绑定函数中使用$root之前添加addDurationValueclick,以提供正确的binding context

foreach绑定中,knockout会在每个addDurationValue对象而不是DurationValue实例中查找DurationValuesViewModel。因此,我们需要指定查找函数的位置。在这种情况下,$root$parent引用相同的对象。

function DurationValue(text) {
  this.text = text;
}

function DurationValuesViewModel() {
  var self = this;

  self.durationValues = ko.observableArray([
    new DurationValue("")
  ]);

  self.addDurationValue = function() {
    self.durationValues.push(new DurationValue(""));

    //Remove current form validation information
    $("form")
      .removeData("validator")
      .removeData("unobtrusiveValidation");

    // Commented for now
    //Parse the form again
    // $.validator.unobtrusive.parse("form");
  };

  self.removeDurationValue = function(durationValue) {
    self.durationValues.remove(durationValue);
  };
}

ko.applyBindings(new DurationValuesViewModel());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!-- ko foreach: durationValues -->
<div class="form-group">
  <!-- ko if: ($index() === 0) -->
  <label for="Values[0].Value">Values</label>
  <!-- /ko -->
  <div class="input-group">
    <input class="form-control" type="text" data-bind="value: text, attr: { name: 'Values[' + $index() + '].Value' }" data-val="true" data-val-required="Value required." />
    <span class="input-group-btn">
          <!-- ko if: ($index() === 0) -->
              <button class="btn btn-outline-secondary" type="button" data-bind="click: $parent.addDurationValue"><i class="fa fa-plus-circle"></i> Add</button>
          <!-- /ko -->
          <!-- ko if: ($index() > 0)-->
              <button class="btn btn-outline-secondary" type="button" data-bind="click: $parent.removeDurationValue"><i class="fa fa-trash"></i> Remove</button>
          <!-- /ko -->
      </span>
  </div>
  <span class="field-validation-valid invalid-feedback" data-bind="attr: { 'data-valmsg-for': 'Values[' + $index() + '].Value' }" data-valmsg-replace="true"></span>
</div>
<!-- /ko -->