Search code examples
twitter-bootstrapslickgrid

Using bootstrap dropdowns in SlickGrid column


In an application that uses Boostrap (3.0) and SlickGrid, i am trying to add a bootsrap dropdown to the column.

var columns = [                    
    {id:"rowNumber", name:"", field: "", editor:Slick.Editors.Text, formatter:RowNumberFormatter, behavior:"select", cssClass:"cell-selection", width:40, cannotTriggerInsert:true, resizable:false, unselectable:true, sortable:false},
    {id:"A", name:"X", field: "A", editor:Slick.Editors.Text, sortable:false, width:120},
    {id:"B", name:"Y", field: "B", readonly:true, width:120,
        formatter: linkFormatter = function (row, cell, value, columnDef, dataContext) {
             var a = 
                '<div class="dropdown">' +
                '  <a class="dropdown-toggle" data-toggle="dropdown" href="#">Action</a>' +
                '  <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">' +
                '      <li><a href="#">Item 1</a></li>' +
                '      <li><a href="#">Item 2</a></li>' +
                '      <li><a href="#">Item 3</a></li>' +
                '      <li><a href="#">Item 4</a></li>' +
                '  </ul>' +
                '</div>    ';
             return a;
        }
    }
];

However it's not working. My guess is that boostrap binding (magic) should be applied after HTML is generated by a formatter. How can i do that?

here a jsFiddle version: http://jsfiddle.net/kilativ/tEU37/


Solution

  • Your actual problem is not what you imagine it is... The dropdown does actually work but it's just not showing up front... and trying to change the z-index does not seem to help. Now I found a partial solution, it's not enough to fix it but it's enough to see the problem.
    Add this piece of CSS:

    .dropdown {
        position: fixed;
    }
    

    and you'll see your menu showing but getting mixed with the rest of the grid, I tried to put all kind of z-index through it but can't get it to fully work. I'll have to dig more, but for now it's a start...

    SOLUTION
    So I spent more time on this, the bounty helps hehe, and found a solution for your problem. First of all, you cannot directly do it inside a formatter as the cell can't grow bigger and z-index does not help for that matter as you are restricted to the cell size. Instead what you have to do is to create an outside <div>, attach it to the body and reposition it with the cell X/Y value, then also make sure the new <div> as a z-index high enough to be on top of the grid... fine but now the question is how do you trigger the action? Simply by subscribing a function to this event onActiveCellChanged(). Taking your example, I moved your code from the formatter to the new function, so I added this piece of code:

    grid.onActiveCellChanged.subscribe(function(e,args){
        $('#myDrop').remove(); // make sure to remove previous dropdown, you don't want to have 100 after a 100 clicks...
        if(args.cell != 2) {
            return;
        }
        var cellPos = args.grid.getActiveCellPosition();
        var elm = $('<div id="myDrop" class="dropdown" style="position:absolute; z-index:10000;">' +
            '  <a class="dropdown-toggle" data-toggle="dropdown" href="#">Action</a>' +
            '  <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">' +
            '      <li><a href="#">Item 1</a></li>' +
            '      <li><a href="#">Item 2</a></li>' +
            '      <li><a href="#">Item 3</a></li>' +
            '      <li><a href="#">Item 4</a></li>' +
            '  </ul>' +
            '</div>    ');
        $('body').append(elm);
        elm.css('top', cellPos.top + 5);
        elm.css('left', cellPos.left + 5);
        $('#myDrop.dropdown-toggle').dropdown('toggle');
        setTimeout(function () {
            $('#myDrop').addClass('open'); // make sure to open the dropdown, delayed so it really open after it's fully created
        }, 50);
    
    });
    

    And I was going to remove your formatter but since you have some random integer value, I action replaced with this piece of code:

    formatter: linkFormatter = function (row, cell, value, columnDef, dataContext) {
        return 'Action';
    }
    

    I'm not sure if the edit of the jsFiddle I made is only temporary but here is the link anyway: jsFiddle
    Also note that you could call the unsubscribe(fn) as well but I didn't find it necessary as dropdown seem to go away without it. You can find the list of available SlickGrid events you can subscribe here wiki/Grid-Events