简体   繁体   中英

binding knockout observable arrays to multiple <ul> elements

For a navigation menu, I have two groups of links, each group and link showing up or not dependent on a user's role. The roles are looked up when the link structure is being built and the list of links is built accordingly. The returned JSON gets parsed, put into observable arrays with no problem, but when I actually try and apply the bindings, the binding fails because the observables are blank. Here is the HTML...

<ul id="user-menu" class="menu" data-bind="foreach: areas">
    <li>
        <a data-bind="attr: { href: areaLink }">
            <img data-bind="attr: { src: iconUri }" />
            <span data-bind="text: areaName"></span>
        </a>
    </li>
</ul>
<ul id="admin-menu" class="menu" data-bind="foreach: adminAreas">
    <li>
        <a data-bind="attr: { href: areaLink }">
            <img data-bind="attr: { src: iconUri }" />
            <span data-bind="text: areaName"></span>
        </a>
    </li>
</ul>

Knockout view model in the background...

var navigation = (function() {

    function Area() {
        var self = this;

        self.areaName = ko.observable();
        self.areaLink = ko.observable();
        self.iconUri = ko.observable();
        self.sequenceNo = ko.observable();
        self.isAdmin = ko.observable();

        self.loadFromVM = function (vm) {
            self.areaName(vm.name || '');
            self.areaLink(vm.link || '');
            self.iconUri(vm.iconUri || '');
            self.sequenceNo(vm.sequenceNo || '');
            self.isAdmin(vm.isAdmin);
        }
    }

    function viewModel() {
        var self = this;

        self.areas = ko.observableArray([]);
        self.adminAreas = ko.observableArray([]);

        self.setup = function () {
            var data = {}; // population with basic session data

            $.getJSON('....php', { JSON.stringify(data) }, function (results) {
                for (var i = 0; i < results.length; i++) {
                    var area = new Area();

                    area.loadFromVM(results[i]);

                    if (area.isAdmin()) {
                        self.adminAreas().push(area);
                    } else {
                        self.areas().push(area);
                    }
                }
            });
        };
    }

    var vmInstance;

    return {
        setup: function () {
            vmInstance = new viewModel();

            vmInstance.setup();

            ko.applyBindings(vmInstance, $('#user-menu')[0]);
            ko.applyBindings(vmInstance, $('#admin-menu')[0]);
        }
    };

})();

And then I bring it together with this in the navigation view file...

    navigation.setup();

So after I get my JSON back, parse it, and organize it when I loop through the success function of the $.getJSON method, putting a watch on self.areas() and self.adminAreas() does show that the arrays have the exact information I want them to. But by the time they have to be applied, calling vmInstance.areas().length or vmInstance.adminAreas().length returns zero. Even more oddly, putting in an alert with the length of the arrays right after the $.getJSON call but within the setup() function will cause the alert to fire first, show zeroes, then goes through the get, populates the array, then fires zeroes again.

Not exactly sure what's going on here, but I can't remember seeing this kind of behavior in another project so I'm not quite sure what I'm doing wrong here. Any ideas or advice would be greatly appreciated.

EDIT: Nevermind on the Fiddle. It doesn't really capture my actual error.

adminarea object is not initialized.you made the adminArea variable but instead of this you have used same area variable to set values.

    var adminArea = new Area();

    adminArea.areaName('test admin area'); 
    adminArea.areaLink('#');
    adminArea.iconUri('http://evernote.com/media/img/getting_started/skitch/windows8/win8-checkmark_icon.png');
    adminArea.sequenceNo(1);
    adminArea.isAdmin(true); 

Fiddle Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM