metismenu icon indicating copy to clipboard operation
metismenu copied to clipboard

Adding items to menu

Open thomasvanlankveld opened this issue 9 years ago • 15 comments

I am building a backbone client app that adds one or more

  • items after fetching data from an API asynchronously. It does not seem to be possible to make metis menu work for
  • items that are added at a later stage. I can call $('#side-menu').metisMenu() a second time but it won't pick up the new items.
  • thomasvanlankveld avatar Sep 17 '14 14:09 thomasvanlankveld

    Yep, same problem here with my Angular app. Any way to circumvent this, otherwise I have to digg into the codebase :)

    juristr avatar Oct 22 '14 14:10 juristr

    Ok, just had a quick look on the codebase

        $.fn[ pluginName ] = function (options) {
            return this.each(function () {
                if (!$.data(this, "plugin_" + pluginName)) {
                    $.data(this, "plugin_" + pluginName, new Plugin(this, options));
                }
            });
        };
    

    As can be seen the plugin remembers whether it has been already initialized. The line if (!$.data(this, "plugin_" + pluginName)) { is the "culprit". Commenting the if and consequently re-calling $(...).metisMenu() seems to work.

    Now there are different possibilities.

    • simply removing the if clause
    • adding a refresh function...like $(...).metisMenu('refresh') or similar...

    Any input from the author would be author @onokumus would be cool, I'm also willing to submit a pull request with the fix. :smile:

    juristr avatar Oct 22 '14 14:10 juristr

    I have noticed that just re-calling $(element).metisMenu(); after adding the items will give the expected results. I have been using this without modifying any of the codebase. However, I'm not sure how this affects any registered events.

    David-Melo avatar Oct 22 '14 15:10 David-Melo

    That's kinda strange as according to the codebase this shouldn't be possible (if I'm not missing something). Are you sure you're using the latest version? Maybe in a previous one the plugin simply didn't have the if clause.

    juristr avatar Oct 22 '14 15:10 juristr

    Agreed it is strange, a refresh method would be nice. I'm using the latest v1.1.1 using the method I mentioned but a neater way to do it would be great.

    David-Melo avatar Oct 22 '14 15:10 David-Melo

    I got around this problem by using jQuery's removeData()

    var sideMenu = $(this.sideMenuContainer);
    sideMenu.removeData("plugin_metisMenu");
    sideMenu.metisMenu();
    

    thomasvanlankveld avatar Oct 22 '14 18:10 thomasvanlankveld

    This problem is caused by it need init again when the dom is changed. Just add one line code to init will be ok.

    $.fn[ pluginName ] = function (options) {
        return this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new Plugin(this, options));
            } 
            // add this case
            else {
                $.data(this, "plugin_" + pluginName).init();
            }
        });
    };
    

    And when you changed dom anywhere, the only thing you need to do is call the following code

    $(selector).metisMenu();
    

    arlen43 avatar Dec 01 '14 09:12 arlen43

    Thanks @thomasvanlankveld that worked for me. Haven't tried @arlen43 's solution.

    dbilovd avatar Apr 02 '15 18:04 dbilovd

    thanks @arlen43 ! your solution worked for me.

    rosesonfire avatar Jul 07 '15 18:07 rosesonfire

    I got it I had to change the code to:

    var sideMenu = $(this.sideMenuContainer);
    sideMenu.removeData("mm");
    sideMenu.metisMenu();
    

    sferoze avatar Aug 13 '15 04:08 sferoze

    Although it doesnt really work that well. I notice that the the navigation dropdown always stays open. And doesn't close. At least one stays open. When I refresh the page it works. We really need to find a way to reload the menu

    sferoze avatar Aug 14 '15 01:08 sferoze

    Ok so actually I figured out how to use @arlen43 solution but with the newest MetisMenu code

      function Plugin(option) {
        return this.each(function() {
          var $this = $(this);
          var data = $this.data('mm');
          var options = $.extend({},
            MetisMenu.DEFAULTS,
            $this.data(),
            typeof option === 'object' && option
          );
    
          if (!data) {
            $this.data('mm', (data = new MetisMenu(this, options)));
          } else {
            $this.data('mm').init();
          }
          if (typeof option === 'string') {
            data[option]();
          }
        });
      }
    

    Now things reload like normal

    sferoze avatar Aug 14 '15 01:08 sferoze

    this worked for me:

    var sideMenu = $('#leftMenu');
    sideMenu.removeData("mm");
    sideMenu.metisMenu();
    

    but, now, when i open a menu, im not able to close it unless i open another, so i always have an open menu.

    salvadoresc avatar Oct 13 '15 18:10 salvadoresc

    See #116

    onokumus avatar Nov 30 '16 07:11 onokumus

    For angularJs I had to add a timeout to wait for the dom change before running metisMenu again

                // After changes to dom
                $timeout(function() {
                    var sideMenu = angular.element('[side-navigation]');
                    sideMenu.removeData("mm");
                    sideMenu.metisMenu();
                });
    

    garhbod avatar Mar 21 '18 01:03 garhbod