初始化空表单分页;knockoutJS

initializing empty form breaks page; knockoutJS

本文关键字:knockoutJS 分页 表单 初始化      更新时间:2023-09-26

使用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>

在knockout中使用这个JS块安全初始化的模式是什么?谢谢你

出现错误的原因是初始任务中的isDone属性没有被设置。你也已经有一个任务视图模型,所以为什么不使用它来初始化你的数组?我刚刚使用了IIFE (立即调用的函数表达式)通过在for循环中更新Task来初始化新任务。您可以手动或以您喜欢的任何方式执行此操作。

还要注意this关键字的使用。参见代码中的self.addTask

我不确定这是否正是你要找的,但我假设你需要一个文本输入输入newTaskText或我错过了什么?无论如何,这似乎是有效的。希望是你问题的答案。

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());
<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>