Telerik Forums
UI for Blazor Forum
0 answers
15 views

Hello everyone,

I am experiencing an issue with my Blazor application and am seeking advice or solutions from anyone who might have had the same issue.

When interacting with the Telerik Editor within a Telerik Grid, clicking inside the editor unexpectedly exits the edit mode. This seems to be linked to event propagation issues, where clicking the editor triggers a propagation that causes the grid to exit edit mode.

Error Messages:

When my issue triggers, I also see the following error in the console:

Uncaught TypeError: Cannot read properties of null (reading 'state')
This occurs within the telerik-blazor.js script and seems related to handling state changes or events. 

I already looked trough Troubleshooting but removing all "StateHasChanged" didn't solve the issue.

What I've Tried:

Implemented JavaScript to stop event propagation using event.stopPropagation() within various event handlers (click, mousedown, etc.).
Checked that the event handlers are correctly assigned and that the JavaScript is initialized at the correct life cycle phase in Blazor (OnAfterRenderAsync).
Removed any redundant StateHasChanged() calls as per Telerik's recommendations to prevent unnecessary re-rendering and potential race conditions.

Code:

The Telerikgrid with the Telerikeditor:

<TelerikGrid Data="ProzessSubPosListe"
             EditMode="@GridEditMode.Incell"
             OnUpdate="@UpdateHandlerProzessPos"
             OnDelete="@DeleteHanlderProzessPos"
             Size="@ThemeConstants.Grid.Size.Small"
             PageSize="100"
             Sortable="true"
             Pageable="false"
             Resizable="true"
             >
    <GridColumns>
        <GridColumn Field="@nameof(ProzessPosClass.Nr)" Title="Nr" Width="10%"></GridColumn>
        <GridColumn Field="@nameof(ProzessPosClass.Title)" Title="Thema" Width="20%"></GridColumn>
        <GridColumn Field="@nameof(ProzessPosClass.ProzessContent)" Title="Beschreibung" Width="20%">
            <EditorTemplate Context="dataItem">
                <div @onclick:stopPropagation="true" @onclick:preventDefault="true">
                @{
                    var item = dataItem as ProzessPosClass;
                    <TelerikEditor @bind-Value="@item.ProzessContent" Width="650px" Height="400px" ></TelerikEditor>
                }
                </div>
            </EditorTemplate>
        </GridColumn>
        <GridCommandColumn Context="Journal" Width="100px">
            <GridCommandButton Command="Save" Icon="@("save")" ShowInEdit="true"></GridCommandButton>
            <GridCommandButton Command="Delete" Icon="@("trash")"></GridCommandButton>
            <GridCommandButton Command="Cancel" Icon="@("cancel")" ShowInEdit="true"></GridCommandButton>
        </GridCommandColumn>
    </GridColumns>
    <NoDataTemplate>
        <strong>Kein Prozessschritt vorhanden</strong>
    </NoDataTemplate>
</TelerikGrid>

OnAfterRenderAsync Method to call the Javascript function.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await JSRuntime.InvokeVoidAsync("setupEditorEventHandling");
    }
}

My Javascript inside of _Layout.cshtml trying to resolve the issue:

 <script>
     function setupEditorEventHandling() {
         console.log("Setup editor event handling");
         document.addEventListener('click', function (event) {
             try {
                 var editor = event.target.closest('.k-editor.telerik-blazor');
                 if (editor) {
                     event.stopPropagation();
                 }
             } catch (error) {
                 console.error('Error handling editor click:', error);
             }
         }, true);
     }
 </script>

How the issue looks like:

Has anyone encountered similar issues with event handling in Blazor applications using that setup? 

Any insights or suggestions would be greatly appreciated.

FateEscape
Top achievements
Rank 1
 asked on 16 Apr 2024
0 answers
9 views
I have a grid that is populated with data from my Database using a DTO and a controller and I have the tooltip working but my issue is that it is the same tooltip for each row in my grid and I can't quite figure out what to do. Here is my grid code, I thought me doing the render would fix it but it doesnt. Any ideas at all would be appreciated
<TelerikGrid class="NewPairsGrid" 
            Data="@Pairs" 
            AutoGenerateColumns="false"       
            RowHeight="15" 
            Height="1000px" 
            Pageable="true"
            PageSize="25"
            Sortable="true"
>
    <GridColumns>

        <GridColumn Field="PairCreatedTimeStamp" Title="Token Age" width="75px">
            <Template Context="dataItem">
                @if (dataItem is EthPairTradeInfoVDto ethPairTradeInfoVDto)
                {
                    var timestamp = CalculateElapsedTime(dataItem as EthPairTradeInfoVDto);
                    <span class="tooltip-target">@timestamp</span>
                    <TelerikTooltip TargetSelector=".tooltip-target" Width="auto" Height="auto" Position="@TooltipPosition.Right">
                    <Template Context="tooltipContext">
                        <span>
                            @RenderTooltipContent(ethPairTradeInfoVDto.PairCreatedTimeStamp)
                        </span>
                    </Template>
            </TelerikTooltip>                 
            </Template>
        </GridColumn>

RenderFragment RenderTooltipContent(DateTime? pairCreatedTimeStamp) => 
    builder =>
    {
        if (pairCreatedTimeStamp.HasValue)
        {
            builder.OpenElement(0, "span");
            builder.AddContent(1, $"Pair Timestamp: {pairCreatedTimeStamp.Value}");
            builder.CloseElement();
        }
    }; 

Jake
Top achievements
Rank 1
 asked on 15 Apr 2024
1 answer
13 views

Hi, 

is there a way to use css to change the telerik menu item border or color when user click on it. After user click on other menu item, the existing old menu item color will remove and the new selected menu item will change the color.

 

Justin
Telerik team
 answered on 15 Apr 2024
0 answers
59 views

Hello,

I have followed the Blazor 8 Getting started instructions but am getting the error Error: Microsoft.JSInterop.JSException: Could not find 'TelerikBlazor.initMediaQuery'.

I have double checked that the  <script src="_content/Telerik.UI.for.Blazor/js/telerik-blazor.js"></script> is in the <head> of the app.razor

i have double checked that the builder.Services.AddTelerikBlazor(); is in the program.cs

and I have the

<TelerikRootComponent>
    @Body
</TelerikRootComponent>

in the root layout component MainLayout.razor.

This error causes my stylesheets not to load. Occasionally the page will load with the stylesheets, but if a clear the cache or do a CTRL-SHIFT-R, I will get the error and my styles will unload.

HALP!

George
Top achievements
Rank 1
Iron
Iron
 asked on 12 Apr 2024
0 answers
26 views

Hello,

I'm working on a .NET8 Blazor webapp with some InteractiveAutoRenderMode. I'm trying to figure out how to code the HTML/Razor in a Blazor component to be able to display a pair of inputs and then bind a collection of a complex type.
I also want the possibility for the user to add more instances to the collection within the UI/component by being able to add more inputs (through a button click) before submitting the form.

I am not sure how to capture the properties inside the complex type collection for the FieldIdentifier instance usually helping with binding and validation? And then how would that work within a loop for the user to be able to add more instances to the collection?

FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityStartTime)

 

The HTML for the pair of inputs looks like this:

ManageProductOffer.razor :

<div class="input-group">
    <label for="@($"""idAvailabilityStartInput""")">
        <input type="datetime-local" id="@($"""idAvailabilityStartInput""")" name="fAvailabilityStart"
                step="any" min="@(TimeProvider.GetLocalNow().LocalDateTime.ToString(SortableDateTimePatternFormat))"
                class="@(ApplyStyleForValidationState(FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities)))"
                value="@(NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityStartTime.ToString(SortableDateTimePatternFormat))"
                @onchange=@(changeEventArgs => TryBindAndValidateField(
                    changeEventArgs: changeEventArgs,
                    fieldIdentifier: FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityStartTime),
                    validationDelegate: () => LimitedAvailability.ValidateLimitedAvailability(NewProductOfferModel!.LimitedAvailabilities[0]))) />
    </label>

    <label for="@($"""idAvailabilityEndInput""")">
        <input type="datetime-local" id="@($"""idAvailabilityEndInput""")" name="fAvailabilityEnd"
                step="any" min="@(TimeProvider.GetLocalNow().LocalDateTime.ToString(SortableDateTimePatternFormat))"
                class="@(ApplyStyleForValidationState(FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities)))"
                value="@(NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityEndTime.ToString(SortableDateTimePatternFormat))"
                @onchange=@(changeEventArgs => TryBindAndValidateField(
                    changeEventArgs: changeEventArgs, 
                    fieldIdentifier: FieldIdentifier.Create(() => NewProductOfferModel!.LimitedAvailabilities[0].LimitedAvailabilityEndTime),
                    validationDelegate: () => LimitedAvailability.ValidateLimitedAvailability(NewProductOfferModel!.LimitedAvailabilities[0]))) />
    </label>
    <small class="">
        <ValidationMessage For="@(() => NewProductOfferModel!.LimitedAvailabilities[0])" />
    </small>
</div>

 

And the code for the model with the complex type collection looks like this:

ProductOfferModel.cs :

public sealed record class ProductOfferModel
{
    public Guid ID { get; init; } = Guid.NewGuid();
    public String ProductOfferDescription { get; set; } = String.Empty;
    public Guid ProductID { get; set; } = Guid.Empty;
    public String ProductDescription { get; set; } = String.Empty;
    public List<LimitedAvailability> LimitedAvailabilities { get; set; } = [new LimitedAvailability()];
}

public sealed record class LimitedAvailability
{
    public Guid ID { get; init; } = Guid.NewGuid();
    public DateTime LimitedAvailabilityStartTime { get; set; } = DateTime.MinValue;
    public DateTime LimitedAvailabilityEndTime { get; set; } = DateTime.MinValue;

    internal static Boolean ValidateLimitedAvailability( LimitedAvailability limitedAvailability )
    {
        ArgumentNullException.ThrowIfNull(limitedAvailability);

        return limitedAvailability.LimitedAvailabilityStartTime < limitedAvailability.LimitedAvailabilityEndTime ?
            true
            : false;
    }
}

 

The (microsoft documentation) mentions supporting complex type and be able to nest and bind, however it does not seems to mention how to capture the FieldIdentifier accessor for a property inside complex type to customize @onchange or @oninput  behavior for example.

Anyone has been solving something similar with using collections of complex types and letting the user add more inputs to the form before submit?

Max
Top achievements
Rank 1
 asked on 12 Apr 2024
1 answer
22 views

Can you explain the differences between the Dialog vs the Window Component?  And maybe give an example of when you should use one over the other?  

IN their current form, they seem pretty similar in implementation and functionality if you put aside the predefined dialogs.  

Dimo
Telerik team
 answered on 12 Apr 2024
1 answer
13 views

I have a button inside of a form that I need to prevent from submitting the form when clicked. How can I add the following to a TelerikButton?

@onclick:preventDefault="true"

@onclick:stopPropagation="true"

Dimo
Telerik team
 answered on 12 Apr 2024
1 answer
17 views
I'd like to move all of the Alignment buttons (along with indent and outdent) into a dropdownlist in the toolbar, so they won't take up as much space. I've tried adding my own custom dropdownlist, but the items I put in it did nothing. Is there a way to accomplish this?
Dimo
Telerik team
 answered on 12 Apr 2024
1 answer
12 views

Hi guys,

I am fairly new to Blazor/Telerik but trying to get this to work.   I introduced OnRead to my code so I can try to capture the grid row count.  The problem is when WorkRecord is called it quits refreshing the grid.  I have to F5 to see my updates.

Its almost as if OnRead gets in the middle of things and doesn't allow things to complete.

Any idea what I am doing wrong here?

 

 

@using Telerik.DataSource.Extensions
@inject DapperRepository<S4PSector4UpdateList> S4GridManager
@inject IJSRuntime js

    @if (@S4Records != null && @cpar != null && @cpar.Initialized == true) 
    {
            //FilterMode="@GridFilterMode.FilterRow"
            <TelerikGrid 
                @ref="@GridRef"
                OnUpdate=@UpdateItem
                Data="@S4Records.ToArray()"
                EnableLoaderContainer="true"
                OnRead="@OnGridRead"
                Pageable="true"
                Sortable="true"
                Resizable="true"
                EditMode="@GridEditMode.Incell"
                Size="@ThemeConstants.Grid.Size.Small"
                SelectionMode="@GridSelectionMode.Single"
                SelectedItems="@SelectedRecord"
                ScrollMode="@GridScrollMode.Scrollable">

                <GridToolBarTemplate>
                <span class="k-toolbar-spacer"></span> @* add this spacer to keep the searchbox on the right *@
                    <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
                    <label for="vehicle1">Not Started/Assigned</label>&nbsp
                    <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
                    <label for="vehicle1">In Progress</label>&nbsp
                    <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
                    <label for="vehicle1">Update Complete</label>&nbsp
                    <input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
                    <label for="vehicle1">Show Only My Records</label>&nbsp
                    <select name="cars" id="cars">
                        <option value="volvo">100</option>
                        <option value="saab">50</option>
                        <option value="opel">20</option>
                        <option value="audi">10</option>
                    </select>
                    <button >Assign Records</button>

                    <GridCommandButton Command="ExcelExport" Icon="@FontIcon.FileExcel">Export to Excel</GridCommandButton>
                    <GridSearchBox Width="200px"/>
                </GridToolBarTemplate>         

                <GridColumns>
                    <GridColumn Field="@nameof(@S4PSector4UpdateList.geid)"  Width="75px" Title="GEID"  Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(@S4PSector4UpdateList.soeid)" Width="55px" Title="SOEID"  Editable="false" HeaderClass="center-me"/>
                    <GridCommandColumn  Width="45px">
                        <GridCommandButton Command="WorkRecord" OnClick="@WorkRecord" Size="@ThemeConstants.Button.Size.Small">Work</GridCommandButton>
                    </GridCommandColumn>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.primaryfullname)" Width="175px" Title="Full Name" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.process_name)" Width="80px" Title="Process Name" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.worked_status)" Width="75px" Title="Status" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.worked_by_user_soeid)" Width="75px" Title="User SOEID" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.worked_by_user_date)" DisplayFormat="{0:MM/dd/yyyy}" Title="Worked Date" Width="85px" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.insertdate)" DisplayFormat="{0:MM/dd/yyyy}" Title="Insert Date" Width="85px" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.note)" Title="Note" Width="150px" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.note_added_by)" Width="80px" Title="Added By" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.note_added_date)" DisplayFormat="{0:MM/dd/yyyy}" Title="Note Date" Width="85px" Editable="false" HeaderClass="center-me"/>
                    <GridColumn Field="@nameof(S4PSector4UpdateList.insertdate)" DisplayFormat="{0:MM/dd/yyyy}" Title="Insert Date" Width="85px" Editable="false" HeaderClass="center-me" />
                    <GridColumn Field="@nameof(S4PSector4UpdateList.sector_4_eligible_group)" Width="130px" Title="Sector 4 Eligible Group" Editable="false" HeaderClass="center-me"/>
                </GridColumns>
            </TelerikGrid>
    }
    @* 👇 Not Visible Components *@
    <DisplayAndLogErrorComponent @ref="displayandlogcomponent"></DisplayAndLogErrorComponent>


@code
{
    [CascadingParameter(Name = "S4pars")] S4CascadingParameters cpar { get; set; }
    [Parameter] public Action Refresh { get; set; }
    List<S4PSector4UpdateList> S4Records { get; set; }
    public TelerikGrid<S4PSector4UpdateList> GridRef { get; set; }
    private DisplayAndLogErrorComponent displayandlogcomponent;
    //public S4PSector4UpdateList SelectedRecord { get; set; }
    public IEnumerable<S4PSector4UpdateList> SelectedRecord { get; set; } = Enumerable.Empty<S4PSector4UpdateList>();
    public int recordcount;

        private async Task OnGridRead(GridReadEventArgs args)
    {
        var result = S4Records.ToDataSourceResult(args.Request);
        args.Data = result.Data;
        args.Total = result.Total;
        recordcount = result.Total;
    }


    protected override async Task OnInitializedAsync()
    {   
        try
        {

            if (cpar.Initialized == true)
            {
                goto finish;
            }

            cpar.Initialized = true;
            goto finish;

        finish:;

            await LoadAllRecords();

        }
        catch (Exception ex)
        {
            displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
        }
        finally
        {
            StateHasChanged();
            Refresh?.Invoke();

        }
    }


    async Task LoadAllRecords()
    {
        try
        {
            await Task.Delay(0);
            var result = await S4GridManager.GetAsync("Select * from wta_application.fn_s4_get_active_records() order by id;");
            S4Records = result.ToList();
        }
        catch (Exception ex)
        {
            displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
        }
        finally
        {
            StateHasChanged();
            Refresh?.Invoke();
        }

    }

    async Task UpdateItem(GridCommandEventArgs args)
    {
        try
        {
            S4PSector4UpdateList item = (S4PSector4UpdateList)args.Item;
            var updated = await S4GridManager.UpdateAsync(item);
            await LoadAllRecords();
            cpar.message = new MessagePars(1, "Record updated successfully!", true);
        }
        catch (Exception ex)
        {
            displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
        }
        finally
        {
            StateHasChanged();
            Refresh?.Invoke(); 
        }

    }

    private async Task WorkRecord(GridCommandEventArgs args)
    {
        try 
        {
            var model = args.Item as S4PSector4UpdateList;

            //Update Table with user soeid and in progress.
            var dictionary = new Dictionary<string, object>
            {
            { "@in_soeid", cpar.authuserinfo.soeid },
            { "@in_id", model.id }
            };
            var parameters = new DynamicParameters(dictionary);
            S4GridManager.ExecuteStoredProcedure("wta_application.sp_s4_work_record", parameters);

            //Update Count Here

            //Copy to clipboard, place success message and select row.
            await js.InvokeVoidAsync("navigator.clipboard.writeText", model.soeid.Trim());
            cpar.message = new MessagePars(1, model.soeid + " copied to clipboard.", true);
            await LoadAllRecords();

            //Highlight the row on the grid they selected
            SelectedRecord = GridRef.Data.Where(x => x.id == model.id).ToList();



        }
        catch (Exception ex)
        {
            displayandlogcomponent.DisplayAndLogError(1, ex, cpar, MethodBase.GetCurrentMethod().DeclaringType.FullName);
        }
        finally
        {
            StateHasChanged();
            Refresh?.Invoke();     
        }
    }

    public void Refreshed()
    {  
        StateHasChanged();
    }




}

                                                                              
Nadezhda Tacheva
Telerik team
 answered on 12 Apr 2024
1 answer
10 views
isn't an update coming for supporting Hijri DateTime or at least changing the Locale and DateTime based on Culture?
Svetoslav Dimitrov
Telerik team
 answered on 12 Apr 2024
Top users last month
Mark
Top achievements
Rank 1
Yurii
Top achievements
Rank 1
Leland
Top achievements
Rank 2
Iron
Iron
Iron
Hon
Top achievements
Rank 1
Iron
Deltaohm
Top achievements
Rank 3
Bronze
Iron
Iron
Want to show your ninja superpower to fellow developers?
Want to show your ninja superpower to fellow developers?