fluentui-blazor
fluentui-blazor copied to clipboard
fix: FluentSelect does not work inside FluentDataGrid
🐛 Bug Report
When using FluentSelect inside FluentDataGrid dropdown is not shown.
💻 Repro or Code Sample
Based on these examples:
https://brave-cliff-0c0c93310.azurestaticapps.net/SelectPage
https://brave-cliff-0c0c93310.azurestaticapps.net/DatagridPage
I would also like some better examples working with enum values and select. I had to write my own code but I think this should be documented better. Added MatSelectItem
as example since it works with FluentDataGrid
. Select works fine with Enum when not used in FluentDataGrid
<p>
<MatSelectItem @bind-Value="@threatDto.Severity" Label="Severity" Items="@SeverityValues" FullWidth="true" Required="true">
</MatSelectItem>
</p>
<p>
<FluentSelect @bind-Value="@threatDto.Severity" Options="@SeverityOptionList" Required="true">
</FluentSelect>
</p>
<FluentDataGrid id="ExternalLinksGrid" RowsData=RowsGrid1 ColumnDefinitions=ExternalLinkColumns GridTemplateColumns="1fr 1fr" TItem=ExternalLink Context="tableRowContext">
<RowItemTemplate>
<FluentDataGridRow>
<FluentDataGridCell GridColumn=1>
<FluentTextField @[email protected]></FluentTextField>
</FluentDataGridCell>
<FluentDataGridCell GridColumn=2>
<FluentSelect @bind-Value="@tableRowContext.LinkType" Options="@LinkTypeOptionList" Required="true">
</FluentSelect>
</FluentDataGridCell>
<FluentDataGridCell GridColumn=3>
<MatSelectItem @bind-Value="@tableRowContext.LinkType" Label="LinkType" Items="@LinkTypeValues" Required="true">
</MatSelectItem>
</FluentDataGridCell>
</FluentDataGridRow>
</RowItemTemplate>
</FluentDataGrid>
public List<ColumnDefinition<ExternalLink>> ExternalLinkColumns = new();
List<Severity?> SeverityValues = Enum.GetValues(typeof(Severity)).Cast<Severity?>().Where(x => x != Severity.None).ToList();
List<LinkType?> LinkTypeValues = Enum.GetValues(typeof(LinkType)).Cast<LinkType?>().Where(x => x != LinkType.None).ToList();
List<Option<Severity?>> SeverityOptionList = Enum.GetValues(typeof(Severity)).Cast<Severity?>().Where(x => x != Severity.None).Select(x => new Option<Severity?> { Key = x.Value, Value = x.Value }).ToList();
List<Option<LinkType?>> LinkTypeOptionList = Enum.GetValues(typeof(LinkType)).Cast<LinkType?>().Where(x => x != LinkType.None).Select(x => new Option<LinkType?> { Key = x, Value = x }).ToList();
List<ExternalLink> RowsGrid1 = new()
{
new ExternalLink(){ Link = "123", LinkType = LinkType.JiraRisk},
new ExternalLink(){ Link = "12345", LinkType = LinkType.OtherHyperlink},
};
protected override void OnInitialized()
{
ExternalLinkColumns.Add(new ColumnDefinition<ExternalLink>("Link", x => x.Link));
ExternalLinkColumns.Add(new ColumnDefinition<ExternalLink>("Link Type", x => x.LinkType));
ExternalLinkColumns.Add(new ColumnDefinition<ExternalLink>("Link Type MatSelectItem", x => x.LinkType));
}
Classes:
[Required, EnumDataType(typeof(Severity))]
public Severity? Severity { get; set; }
public class ExternalLink : Entity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
[MaxLength(2048)]
public string Link { get; set; }
[Required, EnumDataType(typeof(LinkType))]
public LinkType? LinkType { get; set; }
}
public enum LinkType
{
None = 0,
OtherHyperlink = 1,
JiraIssue = 2,
JiraRisk = 3,
}
🤔 Expected Behavior
Should render drop down on click
😯 Current Behavior
No drop down is visible
💁 Possible Solution
🔦 Context
I can not use Fluent UI alone
🌍 Your Environment
- OS & Device: Windows
- Browser Chrome
- .NET and FAST Version .NET 6, Microsoft.Fast.Components.FluentUI 1.5.1 @fluentui/web-components 2.5.4
I believe this is an issue in the underlying web components. Have raised an issue there,
did you have find any solution?
I believe it is solved on the FAST side. Need to wait till it is incorporated in the Fluent dcript. @chrisdholt do you know the schedule for that?
I believe it is solved on the FAST side. Need to wait till it is incorporated in the Fluent dcript. @chrisdholt do you know the schedule for that?
This was part of our current Alpha breaking changes - it will show up in the vNext of Fluent, which will be aligned to Fluent 2 specs. We've currently started work on this, but again, it's part of a larger breaking change. There's a whole history of "why" this previously wasn't working/supported/etc which can provide additional details. One thing you could do in the meantime if you absolutely know and control the stacking context of your application, would be to target the listbox part and use fixed positioning...that would likely allow it to break out.
We can't fix it properly with the current Fluent UI Web Components implementation. As a workaround apply the suggested fixed positioning css
@vnbaaij Could you open this issue again? I have tested with Fluent 2 - Microsoft.Fast.Components.FluentUI 2.14 with @fluentui/[email protected] and it still does not work. Outside FluentDataGrid it works fine. This is a really big drawback since you need to use other libraries for the select.
Code:
<FluentDataGrid id="ExternalLinksGrid" RowsData=RowsGrid1.AsQueryable() GridTemplateColumns="1fr 1fr 1fr" TGridItem=ExternalLink>
<TemplateColumn Title="Link Type">
<FluentSelect Items="@LinkTypeOptionList" TOption="Option<LinkType?>" OptionText="@(i => i.Text.ToString())" OptionValue="@(i => i.Value.ToString())" Required="true" SelectedOptionChanged="@((value) => { context.LinkType = value.Value; })" >
</FluentSelect>
</TemplateColumn>
</FluentDataGrid>
<FluentSelect Items="@LinkTypeOptionList" TOption="Option<LinkType?>" OptionText="@(i => i.Text.ToString())" OptionValue="@(i => i.Value.ToString())" Required="true" SelectedOptionChanged="@((value) => { linkType = value.Value; })">
</FluentSelect>
@code {
private LinkType? linkType;
List<Option<LinkType?>> LinkTypeOptionList = Enum.GetValues(typeof(LinkType)).Cast<LinkType?>().Where(x => x != LinkType.None).Select(x => new Option<LinkType?> { Text = x, Value = x }).ToList();
}
Hi Oscar,
As explained, this is an issue in the underlying web components, We can't really fix it on the Blazor side. As @chrisdholt said, if you absolutely know and control the stacking context of your application, target the listbox part and use fixed positioning. Because we can be sure of this on the Blazor side, we can't fix it like this for everyone.
Trying it locally at least makes it functional:
This is what I changed in the style:
Hello Vincent,
I understand. As I understood it this would be fixed in the Fluent 2 specs and therefore it could be fixed here as well. I did check the issue you opened in the FAST monorepo https://github.com/microsoft/fast/issues/6373 and I will continue to monitor there if anything happens. I will try fixed positioning in the meantime then.
@vnbaaij Trying position: fixed;
with Microsoft.Fast.Components.FluentUI
2.3.3
does not work anymore unfortunately. Looks like this for me with the code above. Any idea on how to get around this now?
Code would be appreciated given that it is a shadow-root element so it requires an override for the constructed stylesheet.
This PR closed your issue in the FAST repo. Anything there that can be used to fix this issue permanently?
If a fix is not possible I think this issue should be reopened since any hack will probably lead to similar braking changes in the future.
Best I can come up with in short term is to go with position: sticky
in overridden CSS.
Gives you something like this:
@vnbaaij position: sticky
works in some cases but if you have a virtualized data grid with fixed height it wont work.
Source enum with None filtered:
public enum Severity
{
None = 0,
Critical = 1,
High = 2,
Medium = 3,
Low = 4
}
I think this issue should be reopened and if this is related to the FAST side I think a new issue should be opened there given that they closed your original issue https://github.com/microsoft/fast/issues/6373 as completed.
Hi Oscar,
I think we got the signals mixed up a bit when discussing this... As Chris mentioned they are working on this for Fluent 2. Contrary to what you might (logically so) think, this is not @fluentui/web-components@2.5.X, but it is the web components V3 branch that this is targeting. Until it lands there and we can wrap those new components, there is not much we can do here than try to fix it as good as we can with CSS tricks
I understand! :)
Should the issue be reopened anyway since it is a bug but it can't be fixed now?
@vnbaaij how can I override position style value to temporarily resolve this issue. I cannot find any document about override css
Hi,
You need to add an isolated css file to your component and then target the listbox part of the select. Something like
:deep .{classname} ::part(listbox) {
position: sticky
}
@ehsangfl More info here: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/css-isolation?view=aspnetcore-7.0
@ehsangfl More info here: https://learn.microsoft.com/en-us/aspnet/core/blazor/components/css-isolation?view=aspnetcore-7.0
I'm didn't familiar with ::deep and ::part. so I learned it from you. thank a lot
I'm using the FluentSelect in a DataGrid cell too. I only see one select option out of many (long list). When I click the down arrow for the Select I get no additional rows to appear. Based on this thread,.. do I set the Class property or the Style property. For the ::deep syntax above, do I say Class="listbox" or Style="listbox"? Is 'classname' = 'fluent-select'? and is that a typo for deep, one colon or two? is 'listbox' the ID of the FluentSelect?
position: sticky
did not work for me. As a workaround I have added the class overflow-column
to those TemplateColumn
s which contains FluentSelect components and added the following component css rule.
<TemplateColumn Title="Column with overflow content" Class="overflow-column">
<FluentSelect ... />
</TemplateColumn>
::deep fluent-data-grid-cell.overflow-column {
overflow: visible;
max-width: 0;
}
As a side effect, when there is not enouph space, a horizontal scrollbar will be shown. But that is fine for my use case.
Can confirm this is a good workaround:
Code I tested with (besides css from post above):
@page "/IssueTester"
<FluentDataGrid Id="ExternalLinksGrid" Items="RowsGrid1.AsQueryable()" GridTemplateColumns="1fr 1fr 1fr" TGridItem=ExternalLink>
<PropertyColumn Property="@(c => c.Link)"></PropertyColumn>
<TemplateColumn Title="Link Type" Class="overflow-column">
<FluentSelect Items="@LinkTypeOptionList" TOption="Option<LinkType?>" OptionText="@(i => i.Text.ToString())" OptionValue="@(i => i.Value.ToString())" Required="true" SelectedOptionChanged="@((value) => { context.LinkType = value.Value; })">
</FluentSelect>
</TemplateColumn>
</FluentDataGrid>
<FluentSelect Items="@LinkTypeOptionList" TOption="Option<LinkType?>" OptionText="@(i => i.Text.ToString())" OptionValue="@(i => i.Value.ToString())" Required="true" SelectedOptionChanged="@((value) => { linkType = value.Value; })">
</FluentSelect>
@code {
private LinkType? linkType;
List<Option<LinkType?>> LinkTypeOptionList = Enum.GetValues(typeof(LinkType)).Cast<LinkType?>().Where(x => x != LinkType.None).Select(x => new Option<LinkType?> { Text = x, Value = x }).ToList();
List<ExternalLink> RowsGrid1 = new()
{
new ExternalLink(){ Link = "123", LinkType = LinkType.JiraRisk},
new ExternalLink(){ Link = "12345", LinkType = LinkType.OtherHyperlink},
};
public class ExternalLink
{
public int Id { get; set; }
public string? Link { get; set; }
public LinkType? LinkType { get; set; }
}
public enum LinkType
{
None = 0,
OtherHyperlink = 1,
JiraIssue = 2,
JiraRisk = 3,
}
public enum Severity
{
None = 0,
Critical = 1,
High = 2,
Medium = 3,
Low = 4
}
}
Closing this issue now that we have 2 possible workarounds.
Maybe some hint or information to this workaround should be added to the documentation of the FluentDataGrid?
I don't want to do that because it kind of sends a signal that the grid can be used as a way to directly edit rows of data. It was not built with that in mind, so we do not want to 'promote' that way of working.
I don't want to do that because it kind of sends a signal that the grid can be used as a way to directly edit rows of data. It was not built with that in mind, so we do not want to 'promote' that way of working.
@vnbaaij Have you tried it with a virtualized data grid?
https://www.fluentui-blazor.net/DataGrid#virtualizedgrid
Sorry, tried what? The workaround with the overflow?
As I explained, I think having an editable grid is not a good idea in general. But doing it on a virtualized grid with (potentially) a huge amount of rows is definitely a very bad idea. (huge load on the DOM)
Sorry, tried what? The workaround with the overflow?
As I explained, I think having an editable grid is not a good idea in general. But doing it on a virtualized grid with (potentially) a huge amount of rows is definitely a very bad idea. (huge load on the DOM)
Yes exactly. It might technically be a bad idea but inline editing is something that users really like. Like the example with template columns.
https://www.fluentui-blazor.net/DataGrid#templatecolumns2