2

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.

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

I've been seeing this for quite too long and couldn't work it out. Thanks my friend.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.