Diver Dan
Diver Dan

Reputation: 9963

Knockout templates and binding to view models

I am having some trouble trying to get knockout templates to work.

I want to use a select list that allows a person to select a value which in turns shows the template.

The template needs to have its own viewmodel properties which are different between each.

I have created a jsfiddle to show the whole thing

I have 2 very basic templates however when I try running the page I get an error. The code is not production codes its simple throw away stuff so naming conventions are not perfect :)

Error: Unable to process binding "foreach: function (){return contacts }" Message: Unable to process binding "template: function (){return { name:contactTypeId} }" Message: Unknown template type: 1

The template do exist

<script type="text/html" id="1">
    <span> Family Template </span>
    <input placeholder="From Mum or Dads side"/>
</script>
<script type="text/html" id="2">
    <span> Friend Template </span>
    <input placeholder="Where did you meet your friend"/>
</script>

I am trying to select the template via a select

<select class="form-control" data-bind="options: $root.contactTypes,
                            optionsText: 'type',
                            optionsValue:'id',
                            value:contactTypeId,
                            optionsCaption: 'Please Select...'"></select>

2 questions.

  1. Why can it not find the template when I select it from the dropdown?
  2. How would I bind the template to have its own model to allow me to save properties.

Update

Thanks to Georges answer below I have the template binding working. Turns out you can't use an int as an ID for a template without calling to

I have updated my model

  self.contactTypeTemplateModel = ko.computed(function () {
         return self.contactTypeId === 2 ? someModelWithWhereDidYouMeet : someOtherModel
    });

    var someModelWithWhereDidYouMeet = {something:ko.observable()};
    var someOtherModel = {something:ko.observable()};

It maybe due to no sleep but I can't get this to work. The console is telling me "something is not defined"

Granted my naming is not good. I have also updated the fiddle

Upvotes: 1

Views: 420

Answers (1)

George Mauer
George Mauer

Reputation: 122052

The problem for question #1 seems to be that you're passing in a number where it expects a string. For whatever reason, it's not being automatically coerced. This solves it.

 template: { name: contactTypeId().toString() }

Even better, create a computed and add a reasonable prefix.

 templateName = ko.computed(function() { return "contact-type-" + contactTypeId() })

As for passing in different models. The template binding supports the data property. Your data property can be a computed based on contactTypeId as well.

So you do your template binding with template: {name: contactTypeTemplateName(), data: contactTypeTemplateModel() }

Where

 self.contactTypeTemplateModel = ko.computed(function() { 
  return self.contactTypeId() === 2 ? someModelWithWhereDidYouMeet 
                                    : someOtherModel })

I should also mention, that unless you reuse these templates independently from each other in lots of places, I wouldn't recommend templates for this. I would just use an if binding.

Upvotes: 0

Related Questions