初始化空表单中断页面; knockoutJS

时间:2016-10-06 04:18:14

标签: javascript jquery html knockout.js

使用knockoutjs我想拥有允许无限选择的表单,但我需要显示表单以便用户知道它存在。从3个表单开始我没问题,所以我想在页面渲染时初始化空对象。出于某种原因,当我初始化一个对象时,它会破坏我的代码:

        function Task(data) {
            this.title=ko.observable(data.title);
            this.isDone=ko.observable(data.isDone);
        }

        function TaskListViewModel() {
            // Data
            var self=this;
            self.tasks=ko.observableArray([]);
            // self.tasks.push({'title': ''})
            self.newTaskText=ko.observable();
            self.incompleteTasks=ko.computed(function() {
                return ko.utils.arrayFilter(self.tasks(), function(task) {
                    return !task.isDone()
                });
            });

            // Operations
            self.addTask=function() {
                self.tasks.push(new Task({
                    title: this.newTaskText()
                }));
                self.newTaskText("");
            };

            self.removeTask=function(task) {
                self.tasks.destroy(task)
            };

            self.incompleteTasks=ko.computed(function() {
                return ko.utils.arrayFilter(self.tasks(),
                    function(task) {
                        return !task.isDone() && !task._destroy
                    });
            });

            self.save=function() {
                $.ajax(".", {
                    data: ko.toJSON({
                        tasks: self.tasks
                    }),
                    type: "post",
                    contentType: "application/json",
                    success: function(result) {
                        alert(result)
                    }
                });
            };

            // load initial state from server, convert to tasks, then add em to self.tasks
            $.getJSON(".", function(allData) {
                var mappedTasks=$.map(allData, function(item) {
                    return new Task(item)
                });
                self.tasks(mappedTasks);
            });
            
            self.tasks.push({'title': ''})
        }
        ko.applyBindings(new TaskListViewModel());
    body { font-family: Helvetica, Arial }
    input:not([type]), input[type=text], input[type=password], select { background-color: #FFFFCC; border: 1px solid gray; padding: 2px; }

    .codeRunner ul {list-style-type: none; margin: 1em 0; background-color: #cde; padding: 1em; border-radius: 0.5em;}
    .codeRunner ul li a { color: Gray; font-size: 90%; text-decoration: none }
    .codeRunner ul li a:hover { text-decoration: underline }
    .codeRunner input:not([type]), input[type=text] { width: 30em; }
    .codeRunner input[disabled] { text-decoration: line-through; border-color: Silver; background-color: Silver; }
    .codeRunner textarea { width: 30em; height: 6em; }
    .codeRunner form { margin-top: 1em; margin-bottom: 1em; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body class="codeRunner">
    <h3> Stuff </h3>
    
        <div data-bind="foreach: tasks, visible: tasks().length > 0">
            <p data-bind="value: title"></p>
        </div>
            
        <ul data-bind="foreach: tasks, visible: tasks().length > 0">
            <li>
                <input data-bind="value: title, disable: isDone" />
                <a href="#" data-bind="click: $parent.removeTask">Delete</a> 
            </li>
        </ul>
          You have <b data-bind="text: incompleteTasks().length">&nbsp;</b> incomplete task(s) 
          <span data-bind="visible: incompleteTasks().length == 0"> -it 's beer time!</span>
              
        <form data-bind="submit: addTask"><button type="submit">Add</button></form>

    <script>

    </script>

</body>

使用这块JS安全地初始化的淘汰模式是什么?谢谢

1 个答案:

答案 0 :(得分:1)

您收到错误的原因是您的初始任务中的isDone属性未设置。您还有一个Task viewModel,那么为什么不用它来初始化您的数组呢?我刚刚使用IIFE(立即调用的函数表达式)通过在Task循环中新增for来初始化新任务。您可以手动或以您喜欢的方式执行此操作。

另请注意您使用this关键字。请参阅代码中的self.addTask

我不确定这是否正是您正在寻找的,但我认为您需要输入文字输入newTaskText或我遗失了什么?无论如何,这似乎有效。希望能回答你的问题。

&#13;
&#13;
function Task(data) {
  this.title = ko.observable(data.title);
  this.isDone = ko.observable(data.isDone || false);
}

function TaskListViewModel() {
  // Data
  var self = this;
  self.tasks = ko.observableArray([]);
  // self.tasks.push({'title': ''})
  self.newTaskText = ko.observable();
  self.incompleteTasks = ko.computed(function() {
    return ko.utils.arrayFilter(self.tasks(), function(task) {
      return !task.isDone()
    });
  });

  // Operations
  self.addTask = function() {
    self.tasks.push(new Task({
      title: self.newTaskText(),
      isDone: false
    }));
    self.newTaskText("");
  };

  self.removeTask = function(task) {
    self.tasks.destroy(task)
  };

  self.incompleteTasks = ko.computed(function() {
    return ko.utils.arrayFilter(self.tasks(),
      function(task) {
        return !task.isDone() && !task._destroy
      });
  });

  (function(numTasks) {
    for (var x = 0; x < numTasks; x++) {
      self.tasks.push(new Task({
        title: ""
      }));
    }
  })(3)

}
ko.applyBindings(new TaskListViewModel());
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body class="codeRunner">
  <h3> Stuff </h3>

  <input data-bind="textInput: newTaskText" type="text" />
  <input data-bind="click: addTask" type="button" value="Add Task" />

  <div data-bind="foreach: tasks, visible: tasks().length > 0">
    <p data-bind="value: title"></p>
  </div>

  <ul data-bind="foreach: tasks, visible: tasks().length > 0">
    <li>
      <input data-bind="value: title, disable: isDone" />
      <a href="#" data-bind="click: $parent.removeTask">Delete</a> 
    </li>
  </ul>
  You have <b data-bind="text: incompleteTasks().length">&nbsp;</b> incomplete task(s)
  <span data-bind="visible: incompleteTasks().length == 0"> -it 's beer time!</span>



  <script>
  </script>

</body>
&#13;
&#13;
&#13;