0

New to knockoutjs and I was following the tutorial on Loading and saving data, but I am having a little trouble. When I push my object to an array the array is empty. I am also using a form. Here is my code,

function Quiz(data) {
    this.quiz_name = ko.observable(data.newQuizName);
    this.quiz_type = ko.observable(data.newQuizType);
}


function QuizViewModel() {
    var self = this;
    self.quizzes = ko.observableArray([]);
    self.newQuizName = ko.observable();
    self.newQuizType = ko.observable();

    self.addQuiz = function () {
        self.quizzes.push(new Quiz({quiz_name: this.newQuizName(), quiz_type: this.newQuizType()}))
        console.log(ko.toJSON(self.quizzes));
    };
}

ko.applyBindings(new QuizViewModel());

and this is my HTML

 <form name="quizzes" id="new-form-quizzes" data-bind="submit: addQuiz" style="display:none">
    <div class="form-group">
        <label for="quiz-name">Quiz Name</label>
        <input type="text" class="form-control" id="quiz-name" aria-describedby="quiz name"
               data-bind="value: newQuizName"
               placeholder="Quize Name"/>
    </div>
    <div class="form-group">
        <label for="quiz-type">Quiz Type</label>
        <input type="text"
               class="form-control"
               id="quiz-type"
               data-bind="value: newQuizType"
               placeholder="Quiz Type"/>
    </div>
    <button type="submit">Save</button>
</form>

Not sure what I am doing wrong as both newQuizName and newQuizType do have values. Any help would be much appreciated.

1 Answer 1

1

You should pass an object (or an array) containing observables as an argument to ko.toJSON. Not the observable itself. So, you need to change your code to:

ko.toJSON(self.quizzes());

ko.toJSON internally calls ko.toJS. The latter method goes through the object and converts each observable to the value of that observable.


After making this change you'll find that there's another problem. The newly added Quiz object has undefined properties. This is because you are passing an object with quiz_name and quiz_type to the Quiz constructor function. But you are accessing newQuizName property from the data parameter. So change your code to:

function Quiz(data) {
  this.quiz_name = ko.observable(data.quiz_name); // these 2 props must be changed
  this.quiz_type = ko.observable(data.quiz_type);
}


function QuizViewModel() {
  var self = this;
  self.quizzes = ko.observableArray([]);
  self.newQuizName = ko.observable();
  self.newQuizType = ko.observable();

  self.addQuiz = function() {
    self.quizzes.push(new Quiz({
      quiz_name: this.newQuizName(),
      quiz_type: this.newQuizType()
    }));

    console.log(ko.toJSON(self.quizzes()));
  };
}

ko.applyBindings(new QuizViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<form name="quizzes" id="new-form-quizzes" data-bind="submit: addQuiz">
  <div class="form-group">
    <label for="quiz-name">Quiz Name</label>
    <input type="text" class="form-control" id="quiz-name" aria-describedby="quiz name" data-bind="value: newQuizName" placeholder="Quize Name" />
  </div>
  <div class="form-group">
    <label for="quiz-type">Quiz Type</label>
    <input type="text" class="form-control" id="quiz-type" data-bind="value: newQuizType" placeholder="Quiz Type" />
  </div>
  <button type="submit">Save</button>
</form>

<!--Table to display the added quizzes-->
<table data-bind="if: quizzes() && quizzes().length > 0">
  <thead>
    <th>Quiz Name</th>
    <th>Quiz Type </th>
  </thead>
  <tbody data-bind="foreach: quizzes">
    <tr>
      <td data-bind="text:quiz_name"></td>
      <td data-bind="text:quiz_type"></td>
    </tr>
  </tbody>
</table>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your help. Managed to get it working. Not sure if this means the tutorial on the site is wrong or I've just completely missed the point. I'll double check.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.