ant-design-blazor / ant-design-blazor

🌈A rich set of enterprise-class UI components based on Ant Design and Blazor.
https://antblazor.com/
MIT License
5.74k stars 1.04k forks source link

Sider component OnCollapsed is never invoked #360

Closed nelsonbatista closed 4 years ago

nelsonbatista commented 4 years ago

Hello,

The layout Sider component has two events: OnCollapsed (an Action) and OnCollapse (an EventCallback). Only the OnCollapse has the [parameter] attribute and is the only one accessible.

When the side collapse is changed (by ToggleCollapsed or OptimizeSize call or Collapsed parameter set), only the OnCollapsed event action is invoked.

With this we cannot have a binding event when the sider is collapsed or not. As I can see, or the OnCollapse event is invoked instead of the OnCollapsed, or the [parameter] attribute must be set for the OnCollapsed event.

Best regards,

ElderJames commented 4 years ago

Thank you for contacting us @nelsonbatista . We have fixed it and try again please.

nelsonbatista commented 4 years ago

Hello ElderJames,

Thanks in advanced for the help. The event OnCollapse is fired as expected, but now the sider is not working properly and the OnCollapse event is fired twice some times. Here is my code:

Sider Collapsible Collapsed=@collapsed Width="300" NoTrigger OnBreakpoint=@OnBreakpointEvent OnCollapse=@OnCollapseEvent Breakpoint="@AntDesign.BreakpointType.Md"

void OnBreakpointEvent(bool isCollapsed)
{
    if (isCollapsed)
    {
        logoTextCss = "logo-text-collapsed";
        logoTextCssInverse = "logo-text-visible";
    }
    else
    {
        logoTextCss = "logo-text-visible";
        logoTextCssInverse = "logo-text-collapsed";
    }
}

void OnCollapseEvent(bool isCollapsed)
{
    if (isCollapsed)
    {
        logoTextCss = "logo-text-collapsed";
        logoTextCssInverse = "logo-text-visible";
    }
    else
    {
        logoTextCss = "logo-text-visible";
        logoTextCssInverse = "logo-text-collapsed";
    }
}

Different behaviors happen if I subscribe the OnBreakpoint event or not.

Without subscribing the OnBreakpoint:

  1. With the window maximized and sider open.

  2. Minimize window to a size under AntDesign.BreakpointType.Md:

    • OnCollapse event is fired with isCollapsed = true
    • OnCollapse event is fired again with isCollapsed = false
    • The result: the menu items collapse but the Sider does not collapsed
  3. Maximize window to a size over AntDesign.BreakpointType.Md:

    • OnCollapse event is fired with isCollapsed = false
    • The result: the menu items open and sider is already open
  4. Toggle Sider and with the sider closed, minimize window to a size under AntDesign.BreakpointType.Md:

    • OnCollapse event is fired with isCollapsed = true
    • The result: the menu items and the Sider stay collapsed
  5. Maximize window to a size over AntDesign.BreakpointType.Md:

    • OnCollapse event is fired with isCollapsed = false
    • OnCollapse event is fired again with isCollapsed = true
    • The result: the menu items open and sider stays closed

With the OnBreakpoint event subscription:

  1. With the window maximized and sider open.

  2. Minimize window to a size under AntDesign.BreakpointType.Md:

    • OnBreakpoint event is fired with isCollapsed = true
    • OnCollapse event is fired with isCollapsed = false
    • OnCollapse event is fired again with isCollapsed = false
    • The result: the menu items does not collapse and the Sider does not collapsed
  3. Maximize window to a size over AntDesign.BreakpointType.Md:

    • OnCollapse event is fired with isCollapsed = false
    • The result: the menu items and sider are already open
  4. Toggle Sider and with the sider closed, minimize window to a size under AntDesign.BreakpointType.Md:

    • OnBreakpoint event is fired with isCollapsed = true
    • OnCollapse event is fired with isCollapsed = true
    • The result: the menu items and the Sider stay collapsed
  5. Maximize window to a size over AntDesign.BreakpointType.Md:

    • OnCollapse event is fired with isCollapsed = false
    • OnCollapse event is fired again with isCollapsed = true
    • The result: the menu items open and sider stays closed

The OnCollapse is fired 2 times when the Sider needs to be resized (to be open or close).

Please escuse me for the long text, I have tried to figure out what happened, without success, that's why I wrote the tests I have made.

Best regards,

ElderJames commented 4 years ago

Hi @nelsonbatista ,this seems a little complicated, could you help to fix this problem?

nelsonbatista commented 4 years ago

Hello ElderJames,

I've downloaded the repository as zip to my PC and I'm trying to create a new Wasm project in the hosts like the AntDesign.Docs.Wasm but I'm always getting the browser error that _content/AntDesign.Docs/css/docs.css and _content/AntDesign/js/ant-design-blazor.js were not found. Where are these files defined? The project AntDesign.Docs.Wasm is also getting this error.

Best regards,

ElderJames commented 4 years ago

You can import them in wwwroot/index.html

nelsonbatista commented 4 years ago

Yes I did that, here is my index.html

`

<link href="css/app.css" rel="stylesheet" />

`

`

<app>Loading...</app>

<div id="blazor-error-ui">
    An unhandled error has occurred.
    <a href="" class="reload">Reload</a>
    <a class="dismiss">🗙</a>
</div>

<script src="_content/AntDesign.Charts/ant-design-charts-blazor.js"></script>
<script src="_content/AntDesign/js/ant-design-blazor.js"></script>
<script src="_content/AntDesign.Docs/js/prism.js"></script>
<script src="_framework/blazor.webassembly.js"></script>

` I add a reference to the project AntDesign.Docs in my programs I added the service builder.Services.AddAntDesignDocs();

ElderJames commented 4 years ago

Oh, you should install npm packages first, and these static files will be generated at build time.

nelsonbatista commented 4 years ago

Hello ElderJames,

I had my dotnet-tools.json file blocked and the npm installed didn't work. I already been able to create a test Wasm project.

I believe the problem is related to the bindings and the inner works of Blazor framework. As soon as we invoke the OnBreakpoint.InvokeAsync(true); my eventcallback is called, but then the ´bool Collapsed´ is called several times with value = false, although we have set isCollapsed earlier to true. I believe this is the result of a state update by the Blazor framework with old values of the variables. I have tried to control the binding, in this case with the Menu and my component but with no success.

The only solution that I got is to deliver the Sider collapse change to the developer. That is, the Private void OptimizeSize will only invoke the OnBreakpoint with true or false and the developer in his component has to handle the collapse itself, by setting the value of the Collapsed with true or false. This solution also offers the developer a better control over the collapse. For example if the user has already selected to collapse the Sider, if the window size is changed, we do not want to change the collapse state.

There is also a bug with the Sider component, when we change the window size. The Private void OptimizeSize is invoked whatever I have a Breakpoint.Width defined or not. I believe that in the OnAfterRenderAsync we should substitute the if (firstRender) by if (firstRender && Breakpoint != null) . Then the Private void OptimizeSize is only called if the developer has defined a Breakpoint size.

The Sider code I got is: ... protected override async Task OnAfterRenderAsync(bool firstRender) { await base.OnAfterRenderAsync(firstRender); if (firstRender && Breakpoint != null) { var dimensions = await JsInvokeAsync(JSInteropConstants.getWindow); DomEventService.AddEventListener("window", "resize", args => OptimizeSize(args.innerWidth)); OptimizeSize(dimensions.innerWidth); } } ... private void OptimizeSize(decimal windowWidth) { if (windowWidth < Breakpoint?.Width) { OnBreakpoint.InvokeAsync(true); } else { OnBreakpoint.InvokeAsync(false); } }

On my component I have:

void OnBreakPoint(bool isCollapsed) { collapsed = isCollapsed; Console.WriteLine($"Breakpoint - Collapsed: {isCollapsed}"); }

The Breakpoint is only used if the developer defines the eventcallback for the ´OnBreakpoint´ and the size for the ´Breakpoint´

This is the solution that I got. I do not know if this your desired behavior for the Sider.

Best Regards,

ElderJames commented 4 years ago

Hi @nelsonbatista , we have fixed this issue, please try again.Thank you for your help!

nelsonbatista commented 4 years ago

Hello Elder James,

It is working for me, I have added the Collapsed attribute updated with what is coming from the bool of the event OnCollapse and OnBreakpoint. Thank you very much for your help.

Best regards,

ElderJames commented 4 years ago

Thank you for your feedback.☺