在 Knockout.js 中初始化空表单分隔页面

问题描述 投票:0回答:1

使用 Knockout.js 我想要拥有允许无限选择的表单,但我需要显示表单,以便用户知道它存在。我可以从 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 进行安全初始化的淘汰赛模式是什么?

javascript jquery html knockout.js
1个回答
1
投票

您收到错误的原因是初始任务中的 isDone 属性未设置。您还已经有了一个 Task viewModel,那么为什么不使用它来初始化您的数组呢?我刚刚使用 IIFE(立即调用函数表达式)通过在

Task
循环中更新
for
来初始化新任务。您可以手动或以您喜欢的任何方式执行此操作。

另请注意您对

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>

© www.soinside.com 2019 - 2024. All rights reserved.