Search code examples
knockout.jsknockout-3.0surveyjs

Adding an editor tab to SurveyJS - not able to bind to model


I'm experimenting with adding an application specific tab to SurveyJS, which isn't natively supported. What I've done so far is adding a Recipients Model, e.g.:

import * as ko from "knockout";

export class RecipientsModel {
    public firstName: string = 'Chris';
    constructor() {}
    public show() {}
}

And a template (recipients.html):

<script type="text/html" id="recipients">
  <div class="form-item form-type-textarea form-item-bulk-accounts">
    <label class="control-label" for="edit-bulk-accounts">Email addresses <span class="form-required" title="This field is required.">*</span></label>
    <div class="form-textarea-wrapper resizable textarea-processed resizable-textarea"><textarea class="form-control form-textarea required" id="edit-bulk-accounts" name="bulk_accounts" cols="60" rows="5"></textarea><div class="grippie"></div></div>
    <div class="description">Email addresses for participants you would like to register.  Enter one per line.</div>
  </div>
  <span data-bind="text: firstName">Test</span>
</script>

I've modified editor.ts so that my tab shows, and the content is populated:

this.recipient = new RecipientsModel();
...
...
...
public showManageRecipients() {
    if (!this.canSwitchViewType(null)) return;
    this.recipient.firstName = 'Chris';
    // this.showSurveyRecipients();
    this.koViewType("recipients")
}

So, with what I have so far I have a tab that shows the static content I want. The next step is to figure out the binding which is currently broken:

knockout-min.js:72 Uncaught ReferenceError: Unable to process binding "template: function(){return { name:'recipients'} }"
Message: Unable to process binding "text: function(){return firstName }"
Message: firstName is not defined
at text (eval at parseBindingsString (knockout-min.js:68), <anonymous>:3:57)
at update (knockout-min.js:98)
at function.a.B.i (knockout-min.js:72)
at Function.Pc (knockout-min.js:51)
at Function.Qc (knockout-min.js:51)
at Function.aa (knockout-min.js:50)
at Object.a.m.a.B (knockout-min.js:49)
at knockout-min.js:72
at Object.q (knockout-min.js:11)
at m (knockout-min.js:71)

As this is my first time messing with either KnockoutJS or SurveyJS, I'm struggling to make this simple binding of a property work. I'm currently going through KnockoutJS documentation but, again, I'm not sure this is the correct path of debugging.

EDIT After more debugging, I've updated my model to set firstName to a ko.observable: firstName = ko.observable("");. And, within SurveyJs codebase I set it using this.recipient.firstName('Chris');. I am now able to use: <span data-bind="text: recipient.firstName">Test</span> which is OK - but I think I should somehow be binding the model in a way that doesn't required the use of recipient.firstName and I can just use firstName. Maybe I'm wrong. END EDIT

So, my main question at this point: How do I make the binding of this.recipient.firstName work in my template?


Solution

  • You could change the binding context using the with binding:

    <script type="text/html" id="recipients">
      <div class="form-item form-type-textarea form-item-bulk-accounts">
        <label class="control-label" for="edit-bulk-accounts">Email addresses <span class="form-required" title="This field is required.">*</span></label>
        <div class="form-textarea-wrapper resizable textarea-processed resizable-textarea"><textarea class="form-control form-textarea required" id="edit-bulk-accounts" name="bulk_accounts" cols="60" rows="5"></textarea><div class="grippie"></div></div>
        <div class="description">Email addresses for participants you would like to register.  Enter one per line.</div>
      </div>
      <!-- ko with: recipient -->
      <span data-bind="text: firstName">Test</span>
      <!-- /ko -->
    </script>