angular-gridster2 icon indicating copy to clipboard operation
angular-gridster2 copied to clipboard

Bug: Grid Margin Bottom for Scroll Vertical not working

Open ea20140129 opened this issue 4 years ago • 13 comments

Hi Tiberiu:

The Grid Margin Bottom option for "Scroll Vertical" does not seem to be working. I tried on the Demo site and does not work there as well. Is this something that can be fixed for "Scroll Vertical"? I'd like to add a margin to the bottom.

Thank you.

ea20140129 avatar Feb 24 '21 21:02 ea20140129

Hi @ea20140129 , This is the behavior of the browsers to ignore the bottom margin when with overflow: auto image

I have no idea how to solve this.

tiberiuzuld avatar Mar 09 '21 14:03 tiberiuzuld

Add the margin to a container inside the gridster-item instead of the gridster-item itself.

<gridster>
    <gridster-item>
        <div style="margin-bottom: 40px;>
            <p>CONTENT</p>
        </div>
    </gridster-item>
</gridster>

austenstone avatar Mar 11 '21 02:03 austenstone

@astone2014 doesn't seem to be working as intended. Still the margin bottom not displaying correctly.

gitalvininfo avatar Jun 19 '21 07:06 gitalvininfo

I'm having the same issue in my application. Margin is overflowing when used with GridType.Fixed

sune-monrad avatar Jul 21 '21 10:07 sune-monrad

Bump, same here. Bottom margin seems to be ignored with either: gridster component css margin, gridster-item css margin and gridsterConfig.outerMarginBottom

michael-soorys avatar Jul 21 '21 11:07 michael-soorys

The workaround mentioned in another issue can also be used here:

Hi @CollinGraf314 , It's not possible because the elements are positioned absolute. And because how position absolute works there is not possible for the grid element to increase in size automatically by the browser.

A workaround for now is to: There is the option to determine the grid size on each itemChangeCallback, check the number of rows the grid and multiply by the fixed height, add margins and set the size on the grid.

Maybe in the future will add this option in the library. Need to think about it.

Originally posted by @tiberiuzuld in https://github.com/tiberiuzuld/angular-gridster2/issues/292#issuecomment-379081675

sune-monrad avatar Jul 21 '21 12:07 sune-monrad

setGridSize may be helpful, I used this to solve my problem.

hungtcs avatar Aug 22 '21 06:08 hungtcs

Our gridType had to be scrollVertical. setGridSize fixes this problem in our case but sadly introduces problems with resizing the grid instead.

Neither of mentioned workarounds above worked.

I ended up with adding a div below the gridster-items that is given the height of the .gridster-column elements plus a padding value. This is done using ngAfterViewChecked to set height of the div if height has changed.

<gridster ...props>     
        <gridster-item [item]="item" *ngFor="let item of gridsterItems" ...props>
                <my-component ...props>
        </gridster-item>
        <div [ngStyle]="{height: gridsterExtendFakePaddingHeight+'px'}"></div>
    </gridster>
ngAfterViewChecked(): void {
        this.refreshGridsterFakePadding();
    }
    private refreshGridsterFakePadding(){
        const gridsterColumn = document.querySelector('.gridster-column') as HTMLElement;
        if(gridsterColumn){
            const height = Number(gridsterColumn?.style.height.replace('px', '')) + 30;
            if(height !== this.gridsterExtendFakePaddingHeight){
                this.gridsterExtendFakePaddingHeight = height;
            }
        }
    }

perhellstream avatar Nov 25 '21 09:11 perhellstream

EDIT: See my new answer below.

OLD: I solved it with a pseudo item:

Component:

@HostBinding('style.--gridster-margin') gridsterMargin!: string;

options: GridsterConfig = {
    initCallback: (instance) => {
        this.gridsterMargin = instance.options.margin + 'px';
    }
}

Scss:

gridster-item::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    width: 1px;
    padding-bottom: var(--gridster-margin);
    pointer-events: none;
}

NePheus avatar Apr 03 '22 14:04 NePheus

@perhellstream Thanks, this works. But for me this was easier:

public ngAfterViewChecked() {
        this.extendedHeight = `${this.grid.gridRows.length * this.grid.curRowHeight - (this.gridOptions.margin || 0)}px`;
  }
    ```

SebastianStehle avatar May 04 '22 12:05 SebastianStehle

Update (better workaround)

My previous workaround attempt (see below) caused an issue with the gridster-preview - the little shadow that follows your gridster-item around - and meant it was rendering at the bottom of the page instead of the correct location beneath the gridster-item. To fix this I had to re-work the workaround in the following way:

Template

<gridster [ngClass]="{'gridster-bottom-padding-fix': !isMobile}">     
  <gridster-item>
    <my-component>
  </gridster-item>
</gridster>

Component

@HostBinding('style.--gridster-fake-padding-height') gridsterFakePaddingHeight!: string;
const options: GridsterConfig = {
  gridType: GridType.Fixed,
  ...
  gridSizeChangedCallback: (grid: GridsterComponentInterface) => {
    this.gridsterFakePaddingHeight = `${grid.rows * grid.curRowHeight}px`;
  },
  ...
 }

Style

.gridster-bottom-padding-fix::after {
  height:  var(--gridster-fake-padding-height);
  display: block;
  content: "";
}

The isMobile is used to hide the fake padding div below the mobileBreakpoint as I found it creates a large empty space. The value isMobile is set using my own custom service which is beyond the scope of this comment.

Old Workaround

@NePheus I couldn't get this solution to work so I took a similar approach to @perhellstream. Following @perhellstream's solution I found it caused a ton of ExpressionChangedAfterItHasBeenCheckedError errors. I also wasn't happy calculating the fake padding during every ngAfterViewChecked cycle.

Instead I used the gridSizeChangedCallback, now the fake padding height is only calculated when the grid size changes:

<gridster>     
  <gridster-item>
    <my-component>
  </gridster-item>
  <div *ngIf="isMobile" [ngStyle]="{height: gridsterExtendFakePaddingHeight+'px'}"></div>
</gridster>
public gridsterFakePaddingHeight: number;
const options: GridsterConfig = {
  gridType: GridType.Fixed,
  ...
  gridSizeChangedCallback: (grid: GridsterComponentInterface) => {
    this.gridsterFakePaddingHeight = grid.rows * grid.curRowHeight;
  },
  ...
 }

r-rayns avatar May 23 '22 15:05 r-rayns

Would using padding around the grid items vs margin be an option?

jasonparallel avatar Oct 26 '22 00:10 jasonparallel

Here is an updated version of my solution, because I forgot some important information to get this work:

Component: (adds the margin as css variable to the component)

import { GridsterConfig, GridsterConfigService } from 'angular-gridster2';

@HostBinding('style.--gridster-margin') gridsterMargin!: string;

options: GridsterConfig = {
    initCallback: (instance) => {
        this.gridsterMargin = `${(instance.options.margin ?? GridsterConfigService.margin)}px`;
    }
}

Scss: (adds a pseudo element to each cell with the margin value of the css variable)

gridster-item {
    overflow: visible;

    &::after {
        content: '';
        position: absolute;
        top: 100%;
        left: 0;
        width: 1px;
        padding-bottom: var(--gridster-margin);
        pointer-events: none;
    }
}

NePheus avatar Nov 14 '22 08:11 NePheus