How to make Gridstack.js widgets vertically responsive?

^_^

I am developing my own dashboard using Gridstack.js. My problem is, I want all of my widgets visible on a single screen page without the need to scroll down. What's possible as of the moment is that widgets were horizontally responsive, that is to say, the width of all widgets adjusts as the screen size changes. But the height isn't. Based on my research on this, I have to change 2 lines of code on the main gridstack.js. I did it but still not solved my problem.

Here is my code:

<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gridstack.all.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gridstack.min.css" />

<div id="gridStackHolder" style="border: 2px solid black; padding: 20px !important;">
<div class="grid-stack" style="background: whitesmoke !important; resize: both; overflow: scroll;">
  <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2" style="background: white !important; border: 1px solid gainsboro !important; border-radius: 5px !important;">
    <div class="grid-stack-item-content">my first widget</div>
  </div>
  <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="4"style="background: white !important; border: 1px solid gainsboro !important; border-radius: 5px !important;">
    <div class="grid-stack-item-content">another widget!</div>
  </div>
</div>
</div>
<script type="text/javascript">
  $('.grid-stack').gridstack();
</script>

If you will run it, try to resize the container, you can see that the width is adjusting accordingly but the height is still, and thus it only creates a scrollbar on the right side of the screen.

Thank you in advance, and happy coding! ^_^

Regards,

Rancho

Upvotes: 2

Views: 3617

Answers (1)

OJB1
OJB1

Reputation: 2785

This had me scratching my head for a while too. I'm using gridstack.js in my .NET Core 5 & JavaScript project.

I am pulling the gridstack js library into my project currently using a CDN, so the links below I have placed in the header of my web page:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/gridstack.min.css" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gridstack-h5.js"></script>

I have a designer page where the user builds their own layout of the gridstack widgets, the grid container has some custom css so it stretches to the bottom of the page:

CSS form the grid container./

.gridContainer {
    position: absolute;
    height: calc(100vh - 245px);
    min-height: calc(100vh - 245px);
    width: 100%;
    min-width: 100%;
    outline: none;
    /*touch-action: none;*/
    background-color: #191919;
    position: relative;
    padding: 0px;
}

The container looks like below:

enter image description here

You'll notice I have an intermediate navbar above the grid container for the dropdown menu options used for configuring the widget content. The above CSS auto calculates/sets the height of the container by using the overall screen height, minus the height of the header/navbar & footer on my web page. Adjust the CSS in your environment to suit...

Now for my grid layout, I have 12 columns and also have the equivalent of 12qty rows to work with too. If you think about the a grid layout, a 12 x 12 grid is the most flexible option because it allows the user to create a the following layouts:

1 way 2 way 3 way 4 way (quad) 6 way 9 way and so on...

The equivalent number of rows are achieved by setting the grid cell height to a % as opposed to a set height. The author of the library himself actually said using % doesn't work, and it didn't for me either until I noticed a specific pattern of behaviour that we can easily work around when initializing the grid.

With the above point in using % for the cell height, when initializing the grid stack layout on page load function, the KEY thing to do here is add one widget and set the height to 12 units. For some reason this does something magic in the library that confirms/registers the current height of the grid container. Once the first widget is rendered, you could delete it straight away and continue adding new ones using a different height without rendering issues.

HTML for the actual grid container:

<div class="container-fluid p-0 mt-1" style="">
    <div class="grid-stack gridContainer" id="gridContainer" style="overflow-y: auto">
        <!-- JS inserts gridstack widgets here. -->
    </div>
</div>

Javascript functions:

window.onload = function () {

    let opts = {
        // see other possible values (best to do in here)
        // Approximate calcs are 100 / 12 rows = 8.3333%
        cellHeight: '8.3333%', 
        //cellHeightThrottle: 200, // Not currently in use...
        margin: '2px',
    }
    grid = GridStack.init(opts);

    // Important Note: Add the first widget so the library registers the container height.
    // Otherwise the drag tool rendering wont work correclty.
    // Once the first widget is added, the same widget can be deleted and the rendering will
    // continue to function correctly.
    var widgetId = getGUIDv4();
    grid.addWidget('<div class="grid-stack-item" id="' + widgetId + '" onmouseup="onMouseUp(this.id)" style="border: 1px solid #495057;"><div class="grid-stack-item-content">Widget</div></div>', { w: 1, h: 12 });
}

The important point to note in the above js function is that I had set the cell height to a %, this ensures that when we enter the full screen mode, the widgets automatically adjust to the height of the full screen. (widget width works regardless)

Once the grid has first loaded and the first widget is rendered i.e. the one that we configured to take a height of 12 units i.e. the full height of the grid container, the user can then re-adjust the height/width of that widget to suit, then contunue adding more widgets to build their choice of layout.

When the next widget is added to the grid, we us a separate function that is called from a button (in my case the plus btn you see on my navbar above the grid container):

function addWidget() {

    var widgetId = getGUIDv4();
    grid.addWidget('<div class="grid-stack-item" id="' + widgetId + '" onmouseup="onMouseUp(this.id)" style="border: 1px solid #495057;"><div class="grid-stack-item-content">Widget</div></div>', { w: 1, h: 1 });
}

// Function toggles the dashboard canvas layout to full screen mode
function goFullScreen() {

    var container = document.getElementById("gridContainer");
    if (container.requestFullScreen) {
        container.requestFullScreen();
    }
    else if (container.webkitRequestFullScreen) {
        container.webkitRequestFullScreen();
    }
    else if (container.mozRequestFullScreen) {
        container.mozRequestFullScreen();
    }
}

Screenshot below shows where I quickly draw a 6 way layout:

enter image description here

And when I hit the full screen button on my navbar, the widgets automatically re-size to fill the full screen:

enter image description here

Upvotes: 2

Related Questions