0

I'm just starting out with Knockout.js, and I've got a query about dynamic HTML.

I'm creating a dynamic Questionnaire. This has;

  • The Main Questionnaire View Model, which contains ...
  • An observableArray of Pages, which contains ...
  • An observableArray of Questions, which contains ...
  • An Array of Options.

I've mapped my options using the $.map function, like;

this.options = $.map(questionOptions, function(text) { 
                                                       return new Option(text) 
                                                     });

I'm generating some html dynamically in the ViewModel, however when I try and concatenate say the Option Text into something like a set of Radio Buttons;

var htmlContent = '';
ko.utils.arrayForEach(_self.options, function (item) {
    htmlContent += '<input type="radio" name="' + ko.utils.unwrapObservable(_self.questionNumber) + '" data-bind="attr: {value: value}, checked: $root.selected" />\r\n';
    htmlContent += '<span>\r\n';
    htmlContent += item.optionText;
    //htmlContent += ko.utils.unwrapObservable(item.optionText); // Doesn't Work
    //htmlContent += item.optionText(); // Doesn't Work
    htmlContent += '</span>\r\n';
                });

return htmlContent;

I end up with a bunch of;

[object Object]

I've tried a couple of alternatives and gotten a bit stuck with where to go..

I'm not sure how to use Templates, as I'm planning on having Text Boxes, Radio Buttons, Drops Downs, Lists, etc all together. But maybe my knowledge is just lacking here!?

Here's a jsFiddle with some example code;

http://jsfiddle.net/PGallagher69/wA6mQ/21/

Any ideas?

1 Answer 1

2

Your optionText is indeed an Option object.

Try:

htmlContent += item.optionText.optionText;

UPDATE:

The real problem lies here:

function PagesViewModel(pageNo, pageHeader, questions) {
    this.pageNumber = ko.observable(pageNo);
    this.pageHeaderText = ko.observable(pageHeader);

    this.questionItems = ko.observableArray($.map(questions, function (n) {
        return [new QuestionViewModel(n.questionType, n.questionNumber, n.questionText, n.pointsBudget, n.options)]
    }));
}

When you're creating your PagesViewModel, the questions parameter is already an array of QuestionViewModel objects, and by assigning this.questionItems with your custom function, you're re-creating the QuestionViewModel, passing it n.options that is already an array of Option objects thus re-wrapping it again with an Option object, and that is why you're eventually gonna need item.optionText.optionText instead of simply item.optionText.

Try this:

function PagesViewModel(pageNo, pageHeader, questions) {
    this.pageNumber = ko.observable(pageNo);
    this.pageHeaderText = ko.observable(pageHeader);
    this.questionItems = ko.observable(questions);
}
Sign up to request clarification or add additional context in comments.

4 Comments

You're Right! How is that happenning, do you know?
Seems like your _self.options is containing double values, stil checking.
I can't see why it's happening... Very confusing!! :-(
Genius! Well spotted! Thanks a million! If only I could vote up twice! Teehee

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.