У меня есть вложенный список HTML, и мне нужно динамически загружать новый элемент, когда я нажимаю, чтобы развернуть один узел. Я нашел и изменил этот фрагмент, но когда я пытаюсь добавить новые узлы в свой список, я получил ошибка:

Uncaught ReferenceError: Unable to parse bindings.
Bindings value: visible: expanded, click: toggle
Message: toggle is not defined

HTML

<!DOCTYPE html>
<html>

<head>
  <link data-require="font-awesome@*" data-semver="3.0.2" rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/3.0.2/css/font-awesome.min.css" />
  <script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
  <script data-require="knockout@*" data-semver="2.3.0" src="http://knockoutjs.com/downloads/knockout-2.3.0.js"></script>
  <script data-require="knockout.mapping@*" data-semver="2.3.5" src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.3.5/knockout.mapping.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
  <script type="text/html" id="tree-node">
    <li>
      <span class="node-toggle" data-bind="visible: expanded, click: toggle">&ndash;</span>
      <span class="node-toggle" data-bind="visible: collapsed, click: toggle">+</span>
      <span class="node-label" data-bind="text: name, click: $root.selected"></span>

      <div data-bind="if: expanded">
        <ul data-bind="template: {name: 'tree-node', foreach: children}"></ul>
      </div>
    </li>
  </script>
</head>

<body>
  <h1>Example Tree</h1>
  <p>Click on the plus sign to expand a node, click on the label to select it.</p>
  <ul data-bind="template: {name: 'tree-node', data: root}"></ul>
  <div data-bind="if: selected">
    <div data-bind="with: selected">
      Selected Node: <span data-bind="text: name"></span>
    </div>
  </div>
</body>

</html>

JS

// Code goes here
$(function() {
  function TreeNode(values) {
      var self = this;
      ko.mapping.fromJS(values, { children: { create: createNode }}, this);
      this.expanded = ko.observable(false);
      this.collapsed = ko.computed(function() {
      return !self.expanded();
    })
  }



  TreeNode.prototype.toggle = function () {
      this.expanded(!this.expanded());
      if (this.expanded() && !this.children().length){
        // This throw an error
        this.children.push(TreeNode(
          {id: "xxxx", name: "Node xxxx", children: []}
          ));
      } 
  };

  function createNode(options) {
      return new TreeNode(options.data);
  }

  var root = new TreeNode({ id: "1", name: "Root", children: [
      { id: "1.1", name: "Node 1", children: [
          {id: "1.1.1", name: "Node 1.1", children: []},
          {id: "1.1.2", name: "Node 1.2", children: []}
      ]},
      { id: "1.2", name: "Node 2", children: []}
  ]});

  var viewModel = {
      root: root,
      selected: ko.observable()
  };

  ko.applyBindings(viewModel, $('html')[0]);
});

CSS

/* Styles go here */

ul, li {
  list-style: none;
}

.node-label {
  cursor: pointer;
}
.node-toggle {
  display: inline-block;
  width: 1em;
  cursor: pointer;
}

В идеале решение должно работать для бесконечных уровней вложенности. Кто-нибудь может мне намекнуть?

0
raben 28 Фев 2016 в 00:29
Добавьте минимальный воспроизводимый пример к вопросу, чтобы мы могли эффективно помочь.
 – 
Jeroen
28 Фев 2016 в 00:30
Пример находится в связанном Plunker, кстати, я редактировал свой вопрос.
 – 
raben
28 Фев 2016 в 00:43
this.children.push(TreeNode( требуется new перед TreeNode
 – 
Roy J
28 Фев 2016 в 00:53
Ты прав! Я чувствую себя немного глупо :) Если вы измените свой комментарий в ответе, я его приму. Спасибо.
 – 
raben
29 Фев 2016 в 03:33

1 ответ

Лучший ответ

TreeNode - это конструктор, но вы вызываете его без new в строке

this.children.push(TreeNode(
  {id: "xxxx", name: "Node xxxx", children: []}
  ));

Это лишь одна из тех ловушек, на которые нужно обращать внимание. Если вы используете строгий режим, любое использование of this в конструкторе, который вы не вызывали с new, будет undefined вместо глобального объекта. Это могло помочь.

1
Roy J 29 Фев 2016 в 05:53