Sorting items in onyx.Menu

I'm trying to dynamically add menu items to, or remove menu items from an onyx.Menu. The idea is to pass controls to the menu, and create components from them. Currently, if I add a new item, it gets appended at the end of the list. However, I want to keep the menu items sorted in a particular order.

This is the code I'm using currently to add and remove items:
enyo.kind({
name: "myMenu"
kind: "onyx.Menu",
addMenuItem: function(menuItem) {
var controls;

menuItem.kind = menuItem.kind || this.defaultKind;

controls = this.controls;
if (!_.find(controls, function(control) {
return control.name === menuItem.name;
})) {
menuItem = this.createComponent(menuItem);
}
},
menuItemComparator: function(a, b) {
/* some sorting stuff... */
},
flow: enyo.inherit(function(sup) {
return function() {
this.children.sort(this.menuItemComparator);
sup.apply(this, arguments);
};
})
});
I tried this with a plain component first, and sorting the children array during the flow worked perfectly. But, the onyx.Menu has a nested scroller, so the children array only contains the scroller, not the menu items. I could retrieve the inserted menu-items in the following way:
var children = this.getScroller().getStrategy().$.client.children;
But that seems rather dirty.. I figure, the onyx.Menu knows to put the newly created menuItem all the way in the scroller strategy's client, so there must be some way to discover where newly-created components go... However, I cannot find out how... Any ideas?

Comments

  • I've also got an alternative strategy, which might be more efficient from a rendering-perspective. But I bump into the same problem there:

    enyo.kind({
    name: "myMenu"
    kind: "onyx.Menu",
    addMenuItem: function(menuItem) {
    var controls, allMenuItems;

    menuItem.kind = menuItem.kind || this.defaultKind;

    controls = this.controls;
    if (!_.find(controls, function(control) {
    return control.name === menuItem.name;
    })) {
    menuItem = this.createComponent(menuItem);

    allMenuItems = menuItem.parent.children;
    allMenuItems.sort(this.menuItemComparator);
    }

    // Render new item
    if (this.hasNode()) {
    menuItem.render();
    }
    },
    menuItemComparator: function(a, b) {
    /* some sorting stuff... */
    }
    });
    In this case, I create the item first, then retrieve the children, sort the list, and render the new item. This works, but there are two issues:

    1) This will sort the entire list every time a single item gets added. If I could find out which component will become the parent, I could load the existing list of children and figure out the correct index at which to insert the new item.
    2) The new menuItem renders at the end of the list, rather than at the correct sort order. I don't know how to fix this either.
  • Hi @ruben_vreeken‌, anytime there is a control with the special name "client", all child components declared on the kind will have this client control as their parent. onyx.Menu has an enyo.Scroller that is named "client", and likewise its strategy has a "client" control as well. See: https://github.com/enyojs/enyo/blob/master/source/kernel/UiComponent.js#L365. Let me know if this helps!
  • Aha, so that's how it's done, makes total sense now thanx!
Sign In or Register to comment.