Search code examples
jqueryknockout.jsjquery-templates

knockout.js and property not being found in Jquery Template


I am getting "caseStudy is not defined" with the below code. I have to add the full prefix app.viewModel.caseStudy.showFlawDetails to not error.

 app.viewModel.caseStudy = {};
        app.viewModel.caseStudy.cases = ko.observableArray();
        app.viewModel.caseStudy.selectedCaseId = ko.observable(0);
        app.viewModel.caseStudy.selectedCase = ko.mapping.fromJS(caseModel);
app.viewModel.caseStudy.showFlawDetails = function (index) {
        console.log(index);
    };
ko.applyBindings(app.viewModel);

<div class="Flaws" data-bind='template: { name: "flawTemplate", data: caseStudy.selectedCase.Flaws }'>
    </div>
    <script id="flawTemplate" type="text/html">
        {{each(index, value) $data}}
        <div class="flaw">
        <div class="Title" data-bind="click: caseStudy.showFlawDetails(index)"> ${value.Title} </div>
        <div class="Items">
            <div>Title: <input type="text" data-bind="value: value.Title" /></div>
            <div>Check: <input type="text" data-bind="value: value.Check" /></div>
            <div>Instructor: <input type="text" data-bind="value: value.Instructor" /></div>
            <div>Keys: <input type="text" data-bind="value: value.Keys" /></div>
            <div>Opponent Init: <input type="text" data-bind="value: value.OpponentInit" /></div>
            <div>Opponent Justification: <input type="text" data-bind="value: value.OpponentJustif" /></div>
            <div>Opponent Communication: <input type="text" data-bind="value: value.OpponentComm"/></div>
            <div>Hint: <input type="text" data-bind="value: Hint"/></div>
            <div>Opponent Incorrect Hint: <input type="text" data-bind="value: value.OpponentIncorrectHint"/></div>
            <div>Prompt: <input type="text" data-bind="value: Prompt" /></div>
            <div>PromptCompletion: <input type="text" data-bind="value: value.PromptCompletion"/></div>
            <div>Opponent Incorrect Prompt: <input type="text" data-bind="value: value.OpponentIncorrectPrompt"/></div>
        </div>
        </div>
        {{/each}}
    </script>

Solution

  • Inside of your flawTemplate the scope is caseStudy.selectedCase.Flaws, so when you put caseStudy.showFlawDetails, it is not found as a property of Flaws or globally.

    So, you can either reference it with app.viewModel.caseStudy.showFlawDetails, if app has global scope (which it seems to since it works for you).

    Otherwise, a good option is to pass the function in via templateOptions. So, you would do:

    data-bind='template: { name: "flawTemplate", data: caseStudy.selectedCase.Flaws, templateOptions: showFlawDetails: caseStudy.showFlawDetails } }'>
    

    Then, you would access it using $item.showFlawDetails

    The click (and event) bindings also expect that you pass it a reference to a function. In your case you are passing it the result of executing the function. Answered it further here: knockout.js calling click even when jquery template is rendered