Skip to content

Conversation

@ksbecker
Copy link
Contributor

@ksbecker ksbecker commented Aug 8, 2024

Pull Request

📖 Description

Introduced the AutoFit property to the FluentDataGrid component, enabling columns to auto-fit the grid width using JavaScript. Updated XML documentation and added a new demo section in DataGridPage.razor to showcase this feature. Created DataGridAutoFit.razor component for demonstration purposes.

Modified FluentDataGrid.razor and FluentDataGrid.razor.cs to implement AutoFit functionality, including invoking a JavaScript function to adjust column widths. Simplified SortByColumnAsync methods using ternary operators.

Updated CSS in FluentDataGrid.razor.css and FluentDataGridCell.razor.css to support AutoFit, ensuring proper styling and visibility of grid cells. Added autoFitGridColumns JavaScript function in FluentDataGrid.razor.js. Removed redundant CSS rules and adjusted formatting for consistency.

🎫 Issues

#2495

👩‍💻 Reviewer Notes

Not much to this.

📑 Test Plan

This is mostly client side code.

✅ Checklist

General

  • I have added tests for my changes.
  • I have tested my changes.
  • I have updated the project documentation to reflect my changes.
  • I have read the CONTRIBUTING documentation and followed the standards for this project.

Component-specific

  • I have added a new component
  • I have added Unit Tests for my new component
  • I have modified an existing component
  • I have validated the Unit Tests for an existing component

⏭ Next Steps

Introduced the AutoFit property to the FluentDataGrid component, enabling columns to auto-fit the grid width using JavaScript. Updated XML documentation and added a new demo section in DataGridPage.razor to showcase this feature. Created DataGridAutoFit.razor component for demonstration purposes.

Modified FluentDataGrid.razor and FluentDataGrid.razor.cs to implement AutoFit functionality, including invoking a JavaScript function to adjust column widths. Simplified SortByColumnAsync methods using ternary operators.

Updated CSS in FluentDataGrid.razor.css and FluentDataGridCell.razor.css to support AutoFit, ensuring proper styling and visibility of grid cells. Added autoFitGridColumns JavaScript function in FluentDataGrid.razor.js. Removed redundant CSS rules and adjusted formatting for consistency.
@dvoituron
Copy link
Collaborator

Can you explain how do you compute the column width?

And why do you use a JavaScript code to do that, and why not use the Flex `auto' property? One problem with using a JS is there are some side effects, like "the columns are not resized with the browser resize" or "the column sizes are recalculated when the user clicks on the col header to sort", ...

@ksbecker
Copy link
Contributor Author

ksbecker commented Aug 9, 2024

Can you explain how do you compute the column width?

And why do you use a JavaScript code to do that, and why not use the Flex `auto' property? One problem with using a JS is there are some side effects, like "the columns are not resized with the browser resize" or "the column sizes are recalculated when the user clicks on the col header to sort", ...

My skill in CSS is limited, so I don't know much about Flex or other CSS abilities which is why I didn't go that route. Also, there is the grid-template-columns attribute, which I've never heard of, so wasn't sure how that works.

Here's how my solution works:

I start by overriding some CSS with the .auto-fit class on the data grid that disables the overflow and text-overflow properties of the cells. I also set the visibility to hidden to temporarily hide the ugliness of the process. This is a technique I've used in the past (Internet Explorer days). It makes the cells invisible but takes up the space it needs to render the content.

Here's the JS pseudo code:

  • Get the available width for the grid
  • Loop through the columns and find (flatMap) the biggest width of each cell of the column
  • Add up those values to see how much room the cell widths exceed the overall available width
  • Calculate the ratio and apply said ratio to each column width while building the grid-template-columns string

Scenario:

  1. Grid width: 800px
  2. Column widths (needed to render full content): 100px, 100px, 50px, 750px = 1000px
  3. Ratio is 800/1000 = 0.8
  4. New column widths: 80px, 80px, 40px, 600px = 800px

For me, this was a simple way to make that first render better. This could be broadened to execute on resize pretty easily. I don't think it's too necessary on sort/pagination as the content typically would be similar in length. This also does not interfere with column resizing by the UI. It simply sets the widths, and the user can resize columns as they see fit.

I implemented this in my project and thought the community could start with this and make it better. If you, or anyone else, has suggestions, I'm happy to learn and would apply changes that make it better.

@dvoituron
Copy link
Collaborator

That's interesting, I think you should add this explanation above the examples, to explain how these column widths are calculated:

  1. Get the available width for the grid
  2. Loop through the columns and find the biggest width of each cell of the column
  3. Add up those values to see how much room the cell widths exceed the overall available width
  4. Calculate the ratio and apply said ratio to each column width while building the GridTemplateColumns string

Next, you need to find a way to avoid "duplicating the configuration": you should only use AutoFit="true" but not force the developer to define GridTemplateColumns. When using AutoFit, GridTemplateColumns should be ignored.

<FluentDataGrid Items="@people" GridTemplateColumns="auto-fit" AutoFit="true">

I also wonder how this "calculation with cells temporarily rendered invisible" functionality will behave on platforms such as MAUI, or with the Virtualization feature. Could you check these two cases?

On the other hand, there's the fit-content attrribute which might help. But I don't think it would be a viable solution.

@dvoituron
Copy link
Collaborator

Other points.

  1. Can you round off the calculated value to avoid unnecessary precision? Which is copied on all lines.
    grid-template-columns="160.18437118437117px 174.6892551892552px 180.9957264957265px 517.1306471306472px
    => grid-template-columns="160px 174px 180px 517px

  2. Why not use the fr unit instead of px? This allows the display to be calculated proportionally when the page is loaded, but adapted if the user resizes the screen.
    grid-template-columns="160fr 174fr 180fr 517fr

peek_4

@ksbecker
Copy link
Contributor Author

ksbecker commented Aug 12, 2024

That's interesting, I think you should add this explanation above the examples, to explain how these column widths are calculated:

  1. Get the available width for the grid
  2. Loop through the columns and find the biggest width of each cell of the column
  3. Add up those values to see how much room the cell widths exceed the overall available width
  4. Calculate the ratio and apply said ratio to each column width while building the GridTemplateColumns string

Next, you need to find a way to avoid "duplicating the configuration": you should only use AutoFit="true" but not force the developer to define GridTemplateColumns. When using AutoFit, GridTemplateColumns should be ignored.

<FluentDataGrid Items="@people" GridTemplateColumns="auto-fit" AutoFit="true">

I also wonder how this "calculation with cells temporarily rendered invisible" functionality will behave on platforms such as MAUI, or with the Virtualization feature. Could you check these two cases?

On the other hand, there's the fit-content attrribute which might help. But I don't think it would be a viable solution.

I tested with virtualization and, no surprise, it doesn't work there. OnAfterRenderAsync is called before the data is rendered. Is there an event/callback after the virtualized rows are rendered? I see that RenderRow is called for each row but don't see where we can know when all rows are done rendering. Maybe disallow auto-fit when Virtualized is turned on?

I've never done a MAUI project so I can't test quickly there. If I have time I can try. Maybe for now just note that it's untested in MAUI?

One thing I noticed with grid-template-columns is that its use here seems atypical. The W3Schools site has a more basic implementation so it doesn't line up with what's going on with FluentDataGrid. This auto-fit wouldn't be necessary (and may not be) if the implementation was more basic. However, this component isn't basic, so I understand that it may have evolved beyond the original CSS design.

EDIT: I also removed the need for double configuration. I didn't like that either. Should we not allow the GridTemplateColumns to be set when AutoFit is true?

@ksbecker
Copy link
Contributor Author

Other points.

  1. Can you round off the calculated value to avoid unnecessary precision? Which is copied on all lines.
    grid-template-columns="160.18437118437117px 174.6892551892552px 180.9957264957265px 517.1306471306472px
    => grid-template-columns="160px 174px 180px 517px
  2. Why not use the fr unit instead of px? This allows the display to be calculated proportionally when the page is loaded, but adapted if the user resizes the screen.
    grid-template-columns="160fr 174fr 180fr 517fr

As I was addressing this, I realized that there was no need to calculate the ratio and all that mess. Basically the fr unit will do that for the browser. So, I reduced it down to loop and build the string using the full max width of each column and using the fr unit instead. I refactored the .js code to make it cleaner.

Kevin Becker and others added 2 commits August 12, 2024 10:10
Updated DataGridPage.razor to correct a typo and provide additional information about the AutoFit parameter. Removed GridTemplateColumns="auto-fit" from DataGridAutoFit.razor as it is now handled internally. Modified OnParametersSetAsync and OnAfterRenderAsync in FluentDataGrid.razor.cs to support AutoFit. Improved autoFitGridColumns function in FluentDataGrid.razor.js.
…d the `Parameter` attribute for `LoadingContent`.
@ksbecker ksbecker requested a review from vnbaaij August 20, 2024 14:38
@vnbaaij vnbaaij changed the title Add AutoFit feature to FluentDataGrid component [DataGrid] Add AutoFit feature to size columns automatically as best as possible Aug 20, 2024
@vnbaaij vnbaaij changed the title [DataGrid] Add AutoFit feature to size columns automatically as best as possible [DataGrid] Add AutoFit feature to size columns automatically as good as possible Aug 20, 2024
@vnbaaij vnbaaij enabled auto-merge (squash) August 20, 2024 18:12
@vnbaaij vnbaaij dismissed dvoituron’s stale review August 20, 2024 18:34

Not current anymore

@vnbaaij vnbaaij disabled auto-merge August 20, 2024 18:42
@vnbaaij vnbaaij merged commit 1aae32f into microsoft:dev Aug 20, 2024
@ksbecker ksbecker deleted the 2495-AutoFit branch August 20, 2024 18:44
@vnbaaij vnbaaij added this to the v4.9.4 milestone Aug 22, 2024
dannyldj pushed a commit to dannyldj/fluentui-blazor that referenced this pull request Sep 26, 2024
…as possible (microsoft#2496)

* Add AutoFit feature to FluentDataGrid component

Introduced the AutoFit property to the FluentDataGrid component, enabling columns to auto-fit the grid width using JavaScript. Updated XML documentation and added a new demo section in DataGridPage.razor to showcase this feature. Created DataGridAutoFit.razor component for demonstration purposes.

Modified FluentDataGrid.razor and FluentDataGrid.razor.cs to implement AutoFit functionality, including invoking a JavaScript function to adjust column widths. Simplified SortByColumnAsync methods using ternary operators.

Updated CSS in FluentDataGrid.razor.css and FluentDataGridCell.razor.css to support AutoFit, ensuring proper styling and visibility of grid cells. Added autoFitGridColumns JavaScript function in FluentDataGrid.razor.js. Removed redundant CSS rules and adjusted formatting for consistency.

* Provide better comment for the AutoFit feature and fix merge conflict artifacts.

* Add AutoFit parameter to FluentDataGrid component

Updated DataGridPage.razor to correct a typo and provide additional information about the AutoFit parameter. Removed GridTemplateColumns="auto-fit" from DataGridAutoFit.razor as it is now handled internally. Modified OnParametersSetAsync and OnAfterRenderAsync in FluentDataGrid.razor.cs to support AutoFit. Improved autoFitGridColumns function in FluentDataGrid.razor.js.

* Place `Parameter` attribute on separate line for `AutoFit`. Also fixed the `Parameter` attribute for `LoadingContent`.

---------

Co-authored-by: Kevin Becker <[email protected]>
Co-authored-by: Denis Voituron <[email protected]>
Co-authored-by: Vincent Baaij <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants