TelerikLoaderComponent strange behaviour

1 Answer 91 Views
Miscellaneous
Jacek
Top achievements
Rank 1
Jacek asked on 03 Aug 2023, 11:28 AM

Could someone tell me why the loader control does not hide and stays in the dialog indefinitely? Even after fetching the data and toggling the visibility of the control to false? I noticed that it disappears only after zooming out of the browser?

Here is my simple code:

@page "/fetchdata"
@using Telerik.Blazor;
@using Telerik.Blazor.Components;
@using Telerik.DataSource;
@using Telerik.FontIcons
@using Telerik.SvgIcons;
@using Telerik.DataSource.Extensions;

<TelerikButton OnClick="@OpenDialogRequestHandler">Click me to open dialog</TelerikButton>

<TelerikDialog
    @bind-Visible="@DialogVisibility"
    ShowCloseButton="true"
    CloseOnOverlayClick="true"
    Title="Test"
    Height="300">
    <DialogContent>
        <TelerikLoaderContainer
            OverlayThemeColor="light"
            Visible="@(ApiDataRequestInProgress)"
            Class="initial-data-loader"
            LoaderType="@LoaderType.InfiniteSpinner"
            Size="@(ThemeConstants.Loader.Size.Medium)">
        </TelerikLoaderContainer>
        <TelerikGrid 
            EnableLoaderContainer="false"
            Sortable="true"
            OnRead="@GridReadHandler"
            TItem="TestObject"
            Height="500px" 
            Width="300px" Data="_testData" 
            SelectionMode="GridSelectionMode.Single">
            <GridColumns>
                <GridColumn Field="@nameof(TestObject.Gid)" Visible="false" Width="0" />
                <GridColumn Field="@nameof(TestObject.TestProperty)" Title="Treść" Width="100%" />
            </GridColumns>
        </TelerikGrid>
    </DialogContent>
</TelerikDialog>

@code {
    bool _dataInitiated = false;
    bool _refreshing = false;
    List<TestObject> _testData = new List<TestObject>();

    async Task GridReadHandler(GridReadEventArgs args)
    {
        if (!_dataInitiated)
        {
            // I don't want to download data in the OnInitialized method because if the form contains a
            // lot of such fields, the page loading will slow down terribly. And this data is only needed
            // if the user opens a dialog box (clicks a button). Otherwise there is no point in downloading them.
            await MakeAPIRequestAsync();
            _dataInitiated = true;
        }

        DataSourceResult result = _testData.ToDataSourceResult(args.Request);
        args.Data = result.Data;
        args.Total = result.Total;
        StateHasChanged();
    }

    void OpenDialogRequestHandler()
    {
        DialogVisibility = true;
    }

    async Task MakeAPIRequestAsync(bool pCzyNieUzywacCache = false)
    {
        try
        {
            // Simulate API request
            await Task.Delay(1000);

            _testData.Clear();
            _testData.Add(new TestObject() { TestProperty = "Alice" });
            _testData.Add(new TestObject() { TestProperty = "Has" });
            _testData.Add(new TestObject() { TestProperty = "A" });
            _testData.Add(new TestObject() { TestProperty = "Cat" });
        }
        finally
        {
            ApiDataRequestInProgress = false;
        }
    }

    public bool ApiDataRequestInProgress { get; set; } = true;

    public bool DialogVisibility { get; set; } = false;

    internal class TestObject
    {
        public Guid Gid { get; set; } = Guid.NewGuid();
        public string TestProperty { get; set; } = string.Empty;
    }
}

1 Answer, 1 is accepted

Sort by
0
Nadezhda Tacheva
Telerik team
answered on 08 Aug 2023, 06:12 AM

Hi Jacek,

Thank you for sending a runnable version of your code!

I see that you are properly setting the visibility of the loader to false after the data is fetched. The missing part in this scenario is that the Dialog is not refreshed to display the updated content. The Dialog is rendered as a child of the TelerikRootComponent, instead of where it is declared. As a result, it doesn't automatically refresh when its content is updated.

To update the Dialog content, you may invoke its Refresh method. I've refactored your code to showcase the difference: https://blazorrepl.telerik.com/cRusOsaK10i6HGYe02.

===

Side note:

You may notice that I also changed the Grid declaration a bit - I removed the Data parameter. Based on your current configuration, I see that you are using both the OnRead event and the Data parameter to pass data to the component which is not supported with the latest product version - see more details in the Data binding basics section.

The last UI for Blazor version that your current setup will work with is 3.0.0 and we generally recommend using latest (currently 4.4.0).

I hope you will find the above information useful. Please let us know if any other questions appear.

Regards,
Nadezhda Tacheva
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Jacek
Top achievements
Rank 1
commented on 24 Aug 2023, 11:33 AM

Hi Nadezhda, i have updated setup to 4.4.1 and applied changes as you told but it has no any positive effect.  The loader control stays as earlier and i can't figure out why :(
Jacek
Top achievements
Rank 1
commented on 24 Aug 2023, 11:45 AM

It works on Your website buy not on the VS.Net project, compiled on "Windows Machine"
Nadezhda Tacheva
Telerik team
commented on 29 Aug 2023, 07:12 AM

Hi Jacek,

I'm sorry to hear the problem still occurs.

To move forward with the investigation, I will need a reproduction, though. Can you please create an isolated sample runnable application that replicates the type and configuration of your app? You may add the example I shared there - use it as a base and change it as needed so that the issue is reproduced.

Please also include the exact steps to perform, so I can hit that problem. Is it only appearing when compiled on "Windows Machine"?

This will allow me to debug on my end and try to find the root cause.

Thank you in advance for your cooperation!

Jacek
Top achievements
Rank 1
commented on 06 Sep 2023, 06:29 AM

Thank you Nadezhda for your help so far. The loader works as it should according to your instructions (the error was on my side) :) However, I have one more problem with this scenario. The problem is with form validation.
When I select the value of the "Test Value" field from the dialog box list, everything is ok. However, when I try to enter the value from my hand, it throws a validation error. The content of the error seems to be for validation
the component itself was substituted, not the model into which the data is inserted. Could you please help me? I am attaching a working, simple project on which the error can be reproduced:

Nadezhda Tacheva
Telerik team
commented on 08 Sep 2023, 12:19 PM

Hi Jacek,

I was having some trouble running the attached app but I isolated the scenario in a standard Blazor app that I created. Even though it is not MAUI, the form and validation behavior are the same and I managed to hit the issue you mentioned.

FluentValidation is not my area of expertise but I will share my thoughts on why the issue might occur.

FluentValidation works with the standard EditContext. However, based on the current configuration, the custom component that holds the TextBox does not have information about the model. It just accepts the string value of the field.

It looks to me that this confuses the validator and it tries to validate the whole component. This is actually the error it throws.

An option you can try is to pass the whole model to the custom component. Inside the component, you can assign the desired string field to the TextBox.

I've extracted the code in REPL to showcase the approach: https://blazorrepl.telerik.com/mnYZuMlm15Ph8fSL31.

I hope this helps.

Jacek
Top achievements
Rank 1
commented on 11 Sep 2023, 12:51 PM

Thank for Your help Nadezhda, it works perfectly using You guidance. The problem is that this component is mend to be used with many different models. So i probably should create two parameters, like those below, to parametrize both Model and its Property:

[Parameter]
public object Model { get; set; }

[Parameter]
public string PropertyName { get; set; }

and somehow pass it to the @bind-value = "[Model.PropertyName]"

Any idea how to insert my properties into  @bind-value = ""?

Nadezhda Tacheva
Telerik team
commented on 14 Sep 2023, 10:44 AM

Hi Jacek,

I am happy to find out my suggestions are useful.

Generally speaking, the most appropriate solution strongly depends on the business case. Indeed, it should be taken into consideration that the custom component is meant to be used with various models. I am not certain if the scenario can be achieved in the way you've listed and I encourage you to research the possibilities here. It may be useful to observe the GetField Method, so you can get the field and its value based on a field name.

The scenario, however, does not target an issue with any UI for Blazor component but rather application specifics and architecture. Thus, the case falls out of the standard support scope.

If you are still facing difficulties with the exact implementation, I will be happy to assist by putting you in touch with our Professional Service team - they can help with such custom solutions as a part of our separate paid offering.

Please let me know if you'd like to pursue this option and I can start the process for you.

Tags
Miscellaneous
Asked by
Jacek
Top achievements
Rank 1
Answers by
Nadezhda Tacheva
Telerik team
Share this question
or