Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grid not resizing with re sizable div #175

Closed
eyandow opened this issue May 1, 2019 · 32 comments
Closed

Grid not resizing with re sizable div #175

eyandow opened this issue May 1, 2019 · 32 comments

Comments

@eyandow
Copy link

eyandow commented May 1, 2019

I'm submitting a bug report

  • Angular Version:
    7.2.14

  • Library Version:
    2.5.3

  • Browser:
    Chrome 73.0.3683.103

  • Language:
    TypeScript 3.1.1

Current behavior:
I have a re-sizable div that can be changed to nearly and height or width on the fly. When the div is adjusted, The grid does not stay inside the dimensions of the div. In fact, it doesn't do anything at all. These are my grid options

<angular-slickgrid gridId="grid1"
      style="width:100%;height:100%"
            [columnDefinitions]="columnDefinitions"
            [gridOptions]="gridOptions"
            [dataset]="dataset"
            (onAngularGridCreated)="angularGridReady($event)">
            >
 this.gridOptions = {
      enableAutoResize: true,       // true by default
      enableCellNavigation: true,
      autoEdit: true, /* when enabled will automatically open the inlined editor as soon as there is a focus on the cell (can be combined with "enableCellNavigation: true"). */
      autoHeight: false,
      autoResize: {
        containerId:`${this.selector}div`,
        delay: 0,
        sidePadding: 4,
        bottomPadding: 4
      }
    };

Setting autoHeight to True doesn't appear to change much

Expected/desired behavior:
Setting the autoResize grid option with the correct container would correctly set the dimensions of the grid. I have searched the documentation on this and am unable to find anything that has been of use.
I have attached an image, if you are able to open those :)
notresize

@ghiscoding
Copy link
Owner

First the autoHeight is probably not what you think it is, it's an option available in the SlickGrid core lib and it basically draw the entire grid height without any scrolling, for example if the grid has 100 items, all 100 items will be shown in the grid and the only scrolling you'll have is the browser scrolling. This option is really badly name, perhaps fullHeight might have been better, but again that comes from the core lib, not mine.

As for the autoResize, which is implemented within my lib, it needs a Div container for it to work properly. Also it uses the window.resize and when you change the grid size dynamically you will find out that it might not always call a resize (probably your problem). For example in our project, we have a sidebar that can be opened and we do this programmatically (by changing Bootstrap col-md-x size) and that doesn't trigger a window.event, so to circumvent this issue, you can call the resize manually like so

  angularGridReady(angularGrid: AngularGridInstance) {
    this.angularGrid = angularGrid;
  }

  closeSidebar() {
    this.isSidebarOpen = false;
    this.angularGrid.resizerService.resizeGrid();
  }

  openSidebar() {
    this.isSidebarOpen = true;
    this.angularGrid.resizerService.resizeGrid();
  }

@ghiscoding
Copy link
Owner

I created a AutoResize - Wiki to provide information on the subject

@ananddotnetdeveloper
Copy link

Hi ,
how to call this two methods closeSidebar and openSidebar

@ghiscoding
Copy link
Owner

ghiscoding commented May 2, 2019

@ananddotnetdeveloper not sure I understand your question.

The Open/Close sidebar are just custom methods in my project, I call them through row click, it has nothing to do with the grid, it's only to tell you that when you change the DOM programmatically (through the Component), you will have to call the resize yourself. Is that more clear?

But if you wish to know how I do it, I got the idea from Atlassian JIRA by the way. I simply have 2 <div> containers, 1 for the grid and 1 for the sidebar. By default the sidebar is hidden (with an *ngIf="isSidebarOpen") and when user click on a grid row, it calls the openSidebar and I change the containers Bootstrap size. If the sidebar is open, I make the grid container use the CSS class col-md-8 (instead of default col-md-12) and the sidebar has the remaining (so col-md-4) and when I close it, I just put back col-md-12 to the grid container and hide away the sidebar, that's all... However when I do that, the grid doesn't auto-resize because that didn't call a window.resize, I have to force the resize like I wrote in earlier post.

@amathew-statestreet-com
Copy link

I had similar issues. I think we still have a defect in the resize code.
class - ResizerService
method - calculateGridNewDimensions

const gridHeight = windowElm.height() || 0;
shouldn't this be
const gridHeight = containerElm.height() || 0;

@ananddotnetdeveloper
Copy link

Hi ,
I solve this problem by adding minWidth in the AutoResize.
When i debug the code the width is getting 300px. By giving a specific value to minWidth it worked for me.
But we have another issue , Only minWidth is working , if you want use min and max width this solution will not help you

@ghiscoding
Copy link
Owner

@amathew-statestreet-com
I tried your change but that won't work since the container height will be nearly 0px (except margins that Bootstrap might had to a container or whatever else) at the beginning which is why I use the browser window height to calculate available area. When I use the code you suggested, it doesn't resize and uses the default minimum size which is 180px (defined here).

I really don't know what your problem are guys, so unless I have a way to replicate, I can't help. At minimum put an animated gif (I use Share-X on Windows) or something that shows the problem, I can't see what you see.

@amathew-statestreet-com
Copy link

amathew-statestreet-com commented May 6, 2019

I have screen layout as in the attachment (info is masked due to privacy). layout has multiple resizable widgets which has grid in it. User can resize the widget by clicking on the double arrow icon on the top right corner of the widget. Since the grid is not contained in the widget/container (containerId in autorezize gridoption is id of div in the widget which resizes when the resize icon is clicked), I can scroll content of the widget and eventually grid disappear as the grid height is calculated more than the container height.

this is fixed by doing 2 things.

  1. As mentioned in the earlier comment, I used containerElm.height() instead of windowElm.height() for calculating the gridheight.
  2. I removed gridOffsetTop from the formula to calculate availableHeight (availableHeight = gridHeight - bottomPadding;)

Not sure if this is the right thing to do
slick

@ghiscoding
Copy link
Owner

So that is because you have 3 grids on the same screen I guess? For most users, using the windowElm.height() would work but if it really causes issues for edge case like yours, I could add a flag to calculate the height using the window or the container.

The ResizerService would have this change

let gridHeight = 0;
let gridOffsetTop = 0;

if (autoResizeOptions.calculateAvailableSizeBy === 'container') {
  // use the container height to calculate grid height without any top offset 
  gridHeight = containerElm.height() || 0;
} else {
  // use the browser window height with its top offset to calculate grid height
  gridHeight = windowElm.height() || 0;
  const coordOffsetTop = gridDomElm.offset();
  gridOffsetTop = (coordOffsetTop !== undefined) ? coordOffsetTop.top : 0;
}

and in your Grid Options, you would use it like so

this.gridOptions = {
  enableAutoResize: true,
  autoResize: {
    calculateAvailableSizeBy: 'container'  // the 2 options would be 'container' | 'window'
  }
}

Not sure about the option flag name yet, calculateAvailableSizeBy, if you have a better name please say so. Would that work for you?

@amathew-statestreet-com
Copy link

thank you!! this would work. Which release will have this enhancement?

@ghiscoding
Copy link
Owner

Sometime this week

@ghiscoding
Copy link
Owner

@eyandow
It's a little hard to help without a full example, but if I take back your original post, you defined the following

<angular-slickgrid gridId="grid1"
-      style="width:100%;height:100%"
            [columnDefinitions]="columnDefinitions"
            [gridOptions]="gridOptions"
            [dataset]="dataset"
            (onAngularGridCreated)="angularGridReady($event)">
            >

What I can say here, is never apply height/width css styling directly on the <angular-slickgrid>, you are bypassing and most probably messing up the autoResize and the ResizerService is probably not doing it's job properly.

@eyandow
Copy link
Author

eyandow commented May 8, 2019

@ghiscoding
I just tried removing the style on directly on the grid and it didn't seem to make a difference.
In ngOnInit, I am doing the following for resizing:

 this.intervalResize = setInterval(()=>{
      var div = document.getElementById(`${this.selector}div`);
      this.angularGrid.resizerService.resizeGrid();

    }, 250);

So it is resizing every 250 milliseconds.

These are my current grid options:

 this.gridOptions = {
      enableAutoResize: true,       // true by default
      enableCellNavigation: true,
      autoEdit: true, /* when enabled will automatically open the inlined editor as soon as there is a focus on the cell (can be combined with "enableCellNavigation: true"). */
      autoHeight: false,
      autoResize: {
        containerId:`${this.selector}div`,
        delay: 0,
        sidePadding: 10,
        bottomPadding: 10
      },
      enableFiltering: true,
      enableRowDetailView: true,

      rowDetailView: {
        // We can load the "process" asynchronously in 3 different ways (aurelia-http-client, aurelia-fetch-client OR even Promise)
        process: (item) => this.getDataForRowDetail(item),
        // process: this.httpFetch.fetch(`api/item/${item.id}`),

        // load only once and reuse the same item detail without calling process method
        loadOnce: false,

        // false by default, clicking anywhere on the row will open the detail view
        // when set to false, only the "+" icon would open the row detail
        // if you use editor or cell navigation you would want this flag set to false (default)
        useRowClick: true,

        // how many grid rows do we want to use for the row detail panel (this is only set once and will be used for all row detail)
        // also note that the detail view adds an extra 1 row for padding purposes
        // so if you choose 4 panelRows, the display will in fact use 5 rows
        panelRows: this.detailViewRowCount,

        // Preload View Template
        // preloadComponent: RowDetailPreloadComponent,

        // ViewModel Template to load when row detail data is ready
        viewComponent: RowdetailViewComponent,
      },
    };

@eyandow
Copy link
Author

eyandow commented May 8, 2019

I don't know why my comments keep going above this as if it is old... interesting

@ghiscoding
Copy link
Owner

@eyandow
Yes I'm not sure why but some of my posts are showing in the future... 🙄 (6 hours from now)

In ngOnInit, I am doing the following for resizing:

 this.intervalResize = setInterval(()=>{
      var div = document.getElementById(`${this.selector}div`);
      this.angularGrid.resizerService.resizeGrid();

    }, 250);

Why are you using a setInterval? It looks like you're trying to bypass the autoResize functionality, if you just want to delay the resize then just pass that as the 1st argument to the resizeGrid, this service functions takes 2 optional arguments (delay and newSizes). So just do
this.angularGrid.resizerService.resizeGrid(250);

Bottom line, don't try to play with the DOM yourself, you might be competing against the resize service and wonder why it doesn't work.

@eyandow
Copy link
Author

eyandow commented May 8, 2019

@ghiscoding
I am using set interval because if I don't call resizeGrid constantly, the grid does not resize when I adjust the containing div. Removing the 'resizegrid' from the interval causes to grid to stay a static size that it was when the page first loaded. I am looking for it to adjust to the height and the width of the containing div, but it doesn't want to do that with autoResize:
image

The grid should be within that red line.

This is my html in case it helps:

<div id="{{selector}}div" dndDropzone (dndDrop)="onDrop($event)"  [dndDisableIf]="isNotEditMode" style="width: 100%; height: 100%;">
    
      <angular-slickgrid gridId="grid1"
            [columnDefinitions]="columnDefinitions"
            [gridOptions]="gridOptions"
            [dataset]="dataset"
            (onAngularGridCreated)="angularGridReady($event)">
            >
  </angular-slickgrid>
</div>

Nothing fancy being done other than the canvas it is on and the resizing.

Is there a way I can have the grid adjust its size when its containing div is resized? I am not trying to delay the resize at all.

@ghiscoding
Copy link
Owner

@eyandow
The grid does the auto-resizing by itself, so long as it's a window resize event that was triggered. If you programmatically change the container size, then you need to use the resizeGrid yourself.

However, your problem is most likely that you don't have the required Container id (a fixed id) for the resize to work. You have a dynamic Container id <div id="{{selector}}div"> and the Resize Service requires the containerId, which most likely doesn't exist, that will most probably never work since the Grid Options must be a fixed string like so

this.gridOptions = {
      autoResize: {
        containerId: 'demo-container', // fixed string
        sidePadding: 15
      },
      enableAutoResize: true,
}

You could maybe try it dynamically with containerId: this.selector + 'div' to match with what you have in the View. But seriously that is a really problematic use case and I'm not sure how to even support that. The gridId and containerId are both things I expect to be defined before the grid even shows up, they are used in the Resizer Service for it to work properly.

@eyandow
Copy link
Author

eyandow commented May 8, 2019

@ghiscoding
I attempted to update my html so the grid had a static container id like so:

<div id="{{selector}}div" dndDropzone (dndDrop)="onDrop($event)"  [dndDisableIf]="isNotEditMode" style="width: 100%; height: 100%;">
   
      <div id="grid-container" style="width:100%; height:100%;">
        <angular-slickgrid gridId="grid1"
          [columnDefinitions]="columnDefinitions"
          [gridOptions]="gridOptions"
          [dataset]="dataset"
          (onAngularGridCreated)="angularGridReady($event)">
        >
        </angular-slickgrid>
    </div>
</div>

grid-container being the id. I updated my grid options to look like this:

autoResize: {
        containerId:'grid-container',
        delay: 0,
        sidePadding: 10,
        bottomPadding: 10
      }

and I am calling resizeGrid() on an interval. The same behavior where the width is adjusted correctly but the height is wrong is happening again. I don't think it is a problem with the containerID, I think it is a problem with the adjustment of the height of the grid. Is there a way I can manually set the height of the grid?

@ghiscoding
Copy link
Owner

@eyandow
Of course you can manually set the height/width of the grid manually, there's a few demo showing that feature too. You can set it like so

<angular-slickgrid gridId="grid1"
                [columnDefinitions]="columnDefinitions"
                [gridOptions]="gridOptions"
                [dataset]="dataset"
                gridHeight="300"
                gridWidth="800">
    </angular-slickgrid>

Your issue might be related to this new feature that I did not push yet, see this previous post and upcoming feature change in next post

@eyandow
Copy link
Author

eyandow commented May 8, 2019

@ghiscoding
Oh yes, I think if the grid calculated the height based on the container it was actually in and no the window, that should work out well. I will wait for that update and stop messing around with the fitting of the grid.
By the way, I tried setting the height of the grid like so:

<angular-slickgrid gridId="grid1"
          [columnDefinitions]="columnDefinitions"
          [gridOptions]="gridOptions"
          [dataset]="dataset"
          gridHeight="height"
          (onAngularGridCreated)="angularGridReady($event)">
        >
this.intervalResize = setInterval(()=>{
      var div = document.getElementById(`${this.selector}div`);
      this.height = `${div.offsetHeight}px`;
      this.angularGrid.resizerService.resizeGrid();

    }, 250);

But this just causes the grid to not appear at all. Do I need to call another method to get re-render the grid when I update this.height object?

@eyandow
Copy link
Author

eyandow commented May 8, 2019

Oh, and one more quick question while I have you. I am attempting to update the 'columnDefinitions' for the grid in a function. I want to do something like this:

this.columnDefinitions = [
      { id:'name', name: 'Name' , field: "name", sortable: true },
      { id:'template', name: 'Template', field: "template", sortable: true},
      { id:'starttime', field: "starttime", name: 'StartTime', sortable: true },
      { id:'endtime', field: "endtime", name: 'EndTime', sortable: true }
    ];

Then, in my method I want to do this:

this.columnDefinitions.push({id:'rpms', name: 'Rpms' , field: "rpms", sortable: true})

What method do I call to update the grid with those new columns?

@ghiscoding
Copy link
Owner

@eyandow
this is totally invalid gridHeight="height", height should be a string in px or in % and that is obviously not. If you want to use a height variable then you should the square bracket [gridHeight]="height"

This Example has the adding of column definition dynamically, the code is here. Please don't mix multiple questions in an issue, this thread starts to be way too long already and there already users in this thread.

@eyandow
Copy link
Author

eyandow commented May 8, 2019

@ghiscoding
Alright, I won't mix the question anymore. I was unaware that was a problem :) Is it alright with you to open new threads for general questions like that, or is there better way of asking questions like that?

@ghiscoding
Copy link
Owner

ghiscoding commented May 8, 2019

@eyandow
For general questions and not issues with the lib, I would prefer that you try Stack Overflow, I check it once in a while there. The good thing about SO is that someone else could answer and that would lower the amount of open issues in the lib, which are not always issues but instead simple questions.

Also note that I have put a lot of effort in creating lots of Wikis and Examples to help everyone (including me) with setup, options and usage, if my Wikis are missing something, then editing or creating new Wikis is an option.

Lastly, please note that I'm mostly the only person maintaining this lib and as most of us, I also happen to have a day job (meaning less time available). The good thing is that we use the lib on our projects at work, which helps with the lib.

@ghiscoding
Copy link
Owner

@amathew-statestreet-com
Hello, I'm not sure if you saw my other post in the PR #179, if you have a chance to review/test it, that would be great, else I will merge it probably tonight.

Thanks

@amathew-statestreet-com
Copy link

sure. I will do a test today and will let you know if everything look ok.

@amathew-statestreet-com

i had some issues when tried to build locally.. it was giving error or TranslateService. i will try tomorrow and will let you know.

@ghiscoding
Copy link
Owner

ghiscoding commented May 10, 2019

@amathew-statestreet-com
I posted a comment in the PR #179

Also note I renamed attachAutoResizeDataGrid to bindAutoResizeDataGrid, just in case you want to copy the Service code only, just rename the method to previous name and you should be good to go.

That might be your problem

@amathew-statestreet-com

Tested. Everything looks fine.. On a second thought, do we need an extra flag in the autoresize option? Can't we do this logic if containerId in the autoresizeoption is empty/null? If I put a containerId in the autoresize option, my expectation is the grid will not go beyond the container and will be resized based on the container.

@ghiscoding
Copy link
Owner

ghiscoding commented May 10, 2019

That would only work if your container has a height (or max-height) calculated or defined by the user or by the CSS calculation, however in our project that doesn't work as my containers don't have any heights from the start. So enabling that new flag on my project totally breaks it, and most probably would break of lot of people's code including the Angular-Slickgrid demo itself (as you can see below, on 1st page load, it has empty space with that flag enable, it works after I resize the browser though). The reason is that I rely on the viewport size to calculate my grid size even if I have a container defined

At the end of the day, I was ok to add a new flag because it wasn't affecting anyone since it was just another option, but I can't do what you suggested.

On Page Load, I got an empty area
image

ghiscoding added a commit that referenced this issue May 10, 2019
feat(resizer): add calculateAvailableSizeBy container option, issue #175
@ghiscoding
Copy link
Owner

The PR was merged with the new option flag and to be on the safe side I pushed a semver minor version.
This is now available under latest version 2.6.0 on NPM

If there's anything else missing, please open a new issue
Cheers

@ghiscoding
Copy link
Owner

@amathew-statestreet-com
I forgot to mention that if you always use the same Grid Options over and over, then just set them as Global Options and be done with it. Local grid options have precedence over the global options, so if you ever wish to override an option, it's super easy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants