1

Javascript is not my strongest part and absolutely not in combination of Blazor but have with Google and some AI get an eventlistener that run code on my Blazor application if browsersize change.
Now I need to do the same with some of my <div id="abc"> because I have components that need to set height / width in pixels.

My Blazorfile :

@inject DivSizeService dServer

.. html ..


@code {
.. 
protected override async Task OnInitializedAsync()
{
    dService.OnDivSizeChanged += HandleDivSizeChanged;  
}

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {

        if (firstRender)
        {
            await dService.StartListeningForDivSizeChanges("abc");
            await UpdateDivSize();
        }
    }

    private async void HandleDivSizeChanged(object sender, DivSizeChangedEventArgs e)
    {
        if (e.ElementId == "abc")
        {
            await UpdateDivSize();
        }
    }

    async Task UpdateDivSize()
    {
        divSize = await dService.GetDivSize("abc");
        Style = "Width: " + (divSize.Width - 50).ToString() + "px; Height: " + 
            (divSize.Height - 50).ToString() + "px;";

        ChildComponent.Refresh // pseudocode
    }

And my DivSizeService (updated StartListening...):

public class DivSizeService
{
    private readonly IJSRuntime _js;

    public event EventHandler<DivSizeChangedEventArgs> OnDivSizeChanged;

    public DivSizeService(IJSRuntime js)
    {
        _js = js;
    }

    public async Task<DivSize> GetDivSize(string elementId)
    {
        return await _js.InvokeAsync<DivSize>("getElementDimensions", elementId);
        //var dimensions = await _js.InvokeAsync<DivSize>("getDimensionsA");
        //return new DivSize { Width = dimensions.Width, Height = dimensions.Height };
    }

    public async Task StartListeningForDivSizeChanges(string elementId)
    {
        await _js.InvokeVoidAsync("registerResizeListener", elementId, DotNetObjectReference.Create(this)); // updated
    }

    [JSInvokable]
    public void HandleDivSizeChanged(string elementId, DivSize newSize)
    {
        OnDivSizeChanged?.Invoke(this, new DivSizeChangedEventArgs(elementId, newSize));
    }
}

public class DivSizeChangedEventArgs : EventArgs
{
    public string ElementId { get; }
    public DivSize NewSize { get; }

    public DivSizeChangedEventArgs(string elementId, DivSize newSize)
    {
        ElementId = elementId;
        NewSize = newSize;
    }
}

And my Javascript (updated window.registerResizeListener):

    window.getElementDimensions = function (elementId) {
        const element = document.getElementById(elementId);
        return {
            width: element ? element.offsetWidth : 0,
            height: element ? element.offsetHeight : 0
        };
    
window.registerResizeListener = (element, dotnetReference) => {
    const observer = new ResizeObserver(entries => {
        for (let entry of entries) {
            const rect = entry.contentRect;
            console.log(entry.contentRect);

            const size = {
                width: rect.width,
                height: rect.height
            };
            dotnetReference.invokeMethodAsync('DivSizeService.HandleDivSizeChanged', element, size);
        }
    });

    observer.observe(document.getElementById(element));
}

My window.getElementDimensions works, I try to run that when browsersize changed but my div won't update size before that event are finished so that makes me get the previos size of my div.

When I use this code above I got :

Exception thrown: 'Microsoft.JSInterop.JSException' in System.Private.CoreLib.dll Exception thrown: 'Microsoft.JSInterop.JSException' in System.Private.CoreLib.dll Microsoft.AspNetCore.Components.Server.Circuits.RemoteRenderer: Warning: Unhandled exception rendering component: Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element'. TypeError: Failed to execute 'observe' on 'ResizeObserver': parameter 1 is not of type 'Element'.

I know that I get element = "abc" in my window.registerResizeElement but I guess it's not the right way to do this? It crash on observer.observe(element);

Update 1:

With help I got so far that my javascript recognize changes to my div id = "abc", but now I got error : Uncaught Error Error: System.ArgumentException: The type 'DivSizeService' does not contain a public invokable method with [JSInvokableAttribute("DivSizeService.HandleDivSizeChanged")].

Update 2: Problem solved!

I'm passing dotNetReference to my javascript, then I don't need to referens that here :

dotnetReference.invokeMethodAsync('DivSizeService.HandleDivSizeChanged', element, size);

The correct solution should be :

dotnetReference.invokeMethodAsync('HandleDivSizeChanged', element, size);

1 Answer 1

0

The line where you get the error is this one:

observer.observe(element);

because you pass element to observe, which is not a collection of elements, but something else, see

await _js.InvokeVoidAsync("registerResizeListener", elementId);

I'm not sure whether an element's id is being passed to the event or the element itself. In either case, you will need to convert it to the correct type, so if element is an id, then this would work

observer.observe(document.querySelectorAll("#" + element));

otherwise, if element is an element, then this would work

observer.observe(document.querySelectorAll("#" + element.id));

It turns out that instead of 'DivSizeService.HandleDivSizeChanged' the text that should have been passed was 'HandleDivSizeChanged' because the method is instance-level and referencing it by the class name is incorrect.

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks, on my page my div id = "abc", and in await _js.InvokeVoidAsync elementId is a string = "abc". I've tried both your example on observer but I got the same error as before. On the window.getElementDimensions, it works to call it and string elementId = "abc".
@TobiasGustafsson can you console.log(element) inside registerResizeListener and tell me the exact result?
it prints : abc
@TobiasGustafsson does observer.observe(document.getElementById(element)); work?
My error dissapear but there is no event trigger if the div change it's size. No codes running.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.