WillC
WillC

Reputation: 2115

KnockoutJs Binding Variable Numbers of Controls

In KnockoutJs, I have a list of controls that I want to bind to the page as in:

{
  ...
  "FirstName": "Fred",
  "LastName": "Jones",
  "Controls": [
    {
      "Name": "ImageSrc"
      "CurrentValue": "/FredJonesPicture.jpg",
      ...etc...
    },
    {
      "Name": "ImageCaption",
      "CurrentValue": "Quarterback Fred Jones",
      ...etc...
    },
    {
      "Name": "HomeTeamScore",
      "CurrentValue": "7",
      ...etc...
    }
   ]
   etc...
}

with a templates (*ImageSrc* etc are placeholders) like :

<script type="text/html" id="template1">
    <div class="mainContent" data-bind="with: Model" >
        <h3 data-bind="text: *ImageCaption*"></h3>
        <img data-bind="attr:{ src: *ImageSrc* }" class="activeImage" />
        <div data-bind="text: *HomeTeamScore*"></div>
    </div>
</script>  

<script type="text/html" id="template2">
    <div class="mainContent" data-bind="with: Model" >
        <h3 data-bind="text: *Quote*"></h3>
        <img data-bind="attr:{ src: *ImageSrc* }" />
        <h3 data-bind="text: *Song*"></h3>
        <img data-bind="attr:{ src: *Icon* }" style="floatleft"  />
        <div data-bind="text: *Band*"></div>
    </div>
</script>  

etc...

The problem is that there can be a multiple possible templates with a variable number of controls (possibly in the hundreds) for each one. There will be only one template per page.

What is the simplest, most efficient syntax to bind to the page? A function that you pass variables to, a custombinding, or is there some sort of built-in binding technique that I am missing?

Upvotes: 0

Views: 71

Answers (2)

WillC
WillC

Reputation: 2115

Here is one answer that I came up with that works but does not seem very efficient:

self.GetControlValue = function (name)
{
    if (self.Controls().length > 0)
    { 
        var control = ko.utils.arrayFirst(self.Controls(), function (c) 
        {
            return c.Name() === name;
        });

        var value = (control) ? control.CurrentValue() : "";
     }
    return value || "";
};

Binding:

<img data-bind="attr:{ src: GetControlValue('ActiveImageSrc') }" />

Upvotes: 0

Roy J
Roy J

Reputation: 43881

It looks like you have a strangely-formed dictionary. If I understand your example code, you want to bind the CurrentValue associated with a Name. If your control structure were like

Controls: {
    ImageSrc: {
        CurrentValue: "/FredJonesPicture.jpg",
        ...
    },
    ...
}

then your binding would be like

    <img data-bind="attr:{ src: Controls.ImgSrc.CurrentValue }" class="activeImage" />

You could write a computed to transform your Controls, if the array structure is not up to you.

Upvotes: 1

Related Questions