Catalin
Catalin

Reputation: 11731

Knockout template not rendering

I have a viewModel which contains an observable folder object (undefined on initialization)

I have a foreach template that should display the files of the folder, which is not working.

jsfiddle

Html

<div data-bind="template: { if: currentFolder(), foreach: currentFolder.files }">
    <div style="padding: 10px; border: 1px solid #000; background-color: #f0f0f0">
        <span data-bind="text: $data"></span>
    </div>
</div>

<button type="button" id="button">Set current folder</button>

Javascript

var viewModel = {
    currentFolder: ko.observable()
};
ko.applyBindings(viewModel);

document.getElementById('button').onclick = addCurrentFolder;

function addCurrentFolder() {
    var folder = {
        files: [ "File 1", "File 2", "File 3" ]
    };
    viewModel.currentFolder(folder);

    // does nothing

    console.log(viewModel.currentFolder());
};

Upvotes: 0

Views: 1404

Answers (3)

HILARUDEEN S ALLAUDEEN
HILARUDEEN S ALLAUDEEN

Reputation: 1752

You have to do data-bind with either observable or observableArray. I have created fiddle for you.

And your html code should be as follows,

<div data-bind="foreach: currentFolder">
    <div style="padding: 10px; border: 1px solid #000; background-color: #f0f0f0">
        <span data-bind="text: $data"></span>
    </div>
</div>

Since I am binding "currentFolder" with "foreach", knockout is expecting currentFolder as an observableArray. So you have to change view model as follows,

var viewModel = {
    currentFolder: ko.observableArray()
};

And then push values to observable array as follows,

viewModel.currentFolder.pushAll([ "File 1", "File 2", "File 3" ])

Fiddle: http://jsfiddle.net/hV89w/12/

EDIT:

You have to change "currentFolder" as an observableArray. Right now, currentFolder().files can render what you want. However, This is not recommended. Because, It wont capture file level changes. I mean, the UI wont update, on doing currentFolder().files.push("File N").

And if you want to update UI, then you have to do like as follows,

var folder = currentFolder();
folder.files.push("File N");
viewModel.currentFolder(folder);

This approach is make all UI refresh. I mean, this will refresh whole UI in following HTML. This process is consider as costlier.

<div data-bind="foreach: currentFolder">
    <div style="padding: 10px; border: 1px solid #000; background-color: #f0f0f0">
        <span data-bind="text: $data"></span>
    </div>
</div>

Upvotes: 0

Thewads
Thewads

Reputation: 5063

Try and execute your currentFolder observable in the foreach

foreach: currentFolder().files

Upvotes: 0

ebohlman
ebohlman

Reputation: 15003

Your foreach binding needs to be foreach: currentFolder().files since currentFolder is an observable containing an object and as such it needs to be invoked in order to "unwrap" its contents.

Upvotes: 1

Related Questions