jmberon
jmberon

Reputation: 195

Binding javascript array object to view using knockout

Im trying to render a menu based on a json object but the links dont get rendered.

function MenuItem(item) {

    this.id = item.id;
    this.name = item.name;
    this.url = item.url;
    this.parentid = item.parentid,
    this.isSelected = ko.observable(item.isSelected);
    this.userRoles = item.userRoles;

    if (item.Items) {
        this.Items = ko.observableArray($.map(item.Items, function (i) {
            return new MenuItem(i);
        }));
    }
    else {
        this.Items = ko.observableArray();
    }
}


function MenuViewModel(root) {

    var self = this;

    self.Root = new MenuItem(root);
}

function SampleMenuData() {
    return {
        id: 0,
        name: "Root",
        url: null,
        parentid: null,
        isSelected: false,
        userRoles: null,
        Items: [
            {
                id: 1,
                name: "Home",
                url: "/home/index",
                parentid: 0,
                isSelected: true,
                userRoles: null,
                Items: {
                },
            },
            {
                id: 4,
                name: "Products",
                url: "/products/index",
                parentid: 0,
                isSelected: false,
                userRoles: null,
                Items: {
                },
            },
        ],
    };
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<h2>Menu</h2>
<nav data-bind="visible: Root.Items().length > 0">
    <ul data-bind="foreach: Root.Items()">
        <li>
            <a data-bind="attr: { href: url, text: name }">
            </a>
        </li>
        <ul data-bind="foreach: Items()">
            <li>
                <a data-bind="attr: { href: $data.url, text: $data.name}"> </a>
            </li>
        </ul>
    </ul>
</nav>

<script>
    $(function() {

        var vm = new MenuViewModel(SampleMenuData());
        ko.applyBindings(vm);        
    });
</script>

If I use something like:

<li data-bind="text: name">  
</li>

It will show the value for name correctly, but I actually need to create link based on url property. You can see example here : http://jsfiddle.net/430szwu2/1/

Any ideas why this wouldnt work ?

Thanks.

Upvotes: 2

Views: 40

Answers (1)

haim770
haim770

Reputation: 49123

You're mistakenly setting text as part of the attr binding-handler value. Try this instead:

<a data-bind="attr: { href: url }, text: name">

Also:

  1. There's no need for the extra $data prefix.

  2. Your SampleMenuData defined the inner Items property as an object instead of array.

See Documentation and updated Fiddle

Upvotes: 2

Related Questions