Knockout JS with Mappings recursive templating

60 views Asked by At

I'm using knockout JS with the mappings plugin:

https://github.com/SteveSanderson/knockout.mapping/tree/master/build/output

It seems I'm unable to access data.

Here is a working example with pure knockout and pure JSON:

http://jsfiddle.net/u0hv6wxe/2/

And here is a broken example with knockout and mappings not rendering anything:

http://jsfiddle.net/95zztzkq/1/

The reason I'm using the mappings is to prevent creating a model with thousands of properties coming from ajax.

Docs on the plugin:

http://knockoutjs.com/documentation/plugins-mapping.html

The JS:

var initialData = {
    '@type': 'type1',
    'contents': [
        {
            '@type' : 'type2',
            'stringx': 'test'
        },
        {
            '@type' : 'type2',
            'stringx': 'test2'
        }
    ]
};
defaultData = ko.mapping.fromJS(initialData);
ko.applyBindings(defaultData);
console.log(defaultData['@type']());
console.log(defaultData.contents()[0]['@type']());
console.log(defaultData.contents()[1]['@type']());

The Templates:

<!-- ko template: { name: 'mainTemplate', data: $data } --><!-- /ko -->

<script id="mainTemplate" type="text/html">
    <!-- ko if: ($data['@type']=='type1') -->
            <div class="Page">
                PageTest
            <!-- ko if: ($data.contents) -->
                    <!-- ko template: { name: 'mainTemplate', foreach: $data.contents } -->
                    <!-- /ko -->
            <!-- /ko -->
            </div>
    <!-- /ko -->    
    <!-- ko if: ($data['@type']=='type2') -->
            <div class="test">
                StringTest <span data-bind="text: stringx"></span>
            </div>
    <!-- /ko -->    
</script>

I've been stuck for 2 days on this issue, all help is greatly appreciated!

Thanks :)

1

There are 1 answers

2
super cool On BEST ANSWER

While checking conditions in view we need to read a observable value using () which will fix the issue

View :

<!-- ko template: { name: 'mainTemplate', data: $data } --><!-- /ko -->

<script id="mainTemplate" type="text/html">
    <!-- ko if: ($data['@type']()=='type1') -->
            <div class="Page">
                PageTest
            <!-- ko if: ($data.contents) -->
                    <!-- ko template: { name: 'mainTemplate', foreach: $data.contents } -->
                    <!-- /ko -->
            <!-- /ko -->
            </div>
    <!-- /ko -->    
    <!-- ko if: ($data['@type']()=='type2') -->
            <div class="test">
                StringTest <span data-bind="text: stringx"></span>
            </div>
    <!-- /ko -->    
</script>

working fiddle here