Completed
Last Updated: 11 Apr 2024 10:26 by ADMIN
Release 2024 Q2 (May)
Doug
Created on: 10 Mar 2021 09:00
Category: Window
Type: Feature Request
32
Add restriction zone for the Window component

You can move a modal window past the bottom and out of view. At that point the only way to get back to it is to zoom out on the browser. Similarly, if you drag a window to the top, you can move it so high that the title bar is out of view. You can still see the bottom part of the window but even if you zoom out you can't get back to the title bar so the only thing you can do is to either escape out of the window or hope you have Ok/Cancel still visible.

---

ADMIN EDIT

Until a feature is implemented that can do this automatically (whether behind a flag like in our WebForms suite or not), you can handle the window events to check the Top and Left values and compare them with the viewport and the window size.

Here is a basic example:

<TelerikWindow Left="@TheLeft" Top="@TheTop" Draggable="true"
               LeftChanged="@LeftChangedHandler" TopChanged="@TopChangedHandler"
               Visible="true" Width="400px" Height="300px">
    <WindowTitle>Drag me!</WindowTitle>
    <WindowContent>When using Left and Top, make sure to update them in the view-model.</WindowContent>
    <WindowActions>
        <WindowAction Name="Minimize"></WindowAction>
        <WindowAction Name="Maximize"></WindowAction>
    </WindowActions>
</TelerikWindow>

@code{
    string TheLeft { get; set; } = "50px";
    string TheTop { get; set; } = "50px";

    async Task LeftChangedHandler(string currLeft)
    {
        float leftValue = float.Parse(currLeft.Replace("px", ""));
        Console.WriteLine("left " + leftValue);
        //left boundary
        if (leftValue < 0)
        {
            currLeft = "0px";
        }
        //right boundary - replace hardcoded values with current values from the viewport size
        //and take into account the dimensions of your window. This sample hardcodes values for brevity and clarity
        //you may find useful packages like this to get the viewport size https://www.nuget.org/packages/BlazorPro.BlazorSize/
        if (leftValue > 1000)
        {
            currLeft = "1000px";
        }


        TheLeft = currLeft;

        await DelayedRender();
    }

    async Task TopChangedHandler(string currTop)
    {
        float topValue = float.Parse(currTop.Replace("px", ""));
        Console.WriteLine("top: " + topValue);

        //top boundary
        if (topValue < 0)
        {
            currTop = "0px";
        }
        //bottom boundary - replace hardcoded values with current values from the viewport size
        //and take into account the dimensions of your window
        if (topValue > 600)
        {
            currTop = "600px";
        }

        TheTop = currTop;

        await DelayedRender();
    }

    async Task DelayedRender()
    {
        await Task.Run(async () =>
        {
            await Task.Delay(30);
            await InvokeAsync(StateHasChanged);
        });
    }
}

---

8 comments
ADMIN
Dimo
Posted on: 28 Feb 2022 18:05

Thanks for sharing your implementation, Victor.

"Unplanned" status means we confirm the discussed behavior is a valid feature request, however, we have no specific short-term plans to implement it, due to tasks with higher priority. Short-term = up to a few months.

So if you prefer a more neat code immediately, you can do some refactoring.

Regards,
Dimo
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.

Victor
Posted on: 28 Feb 2022 17:29

TY Dimo that does get things working.  I made a subtle change that ensures the position is never off by 1px

https://blazorrepl.telerik.com/QGacmsFL22CYpJCa36

 

Are there any plans to add this kind of support to TelerikWindow?  Otherwise I'll take a stab at sub-classing it myself.

ADMIN
Dimo
Posted on: 28 Feb 2022 14:07

Hi Victor,

If you drag the Window outside both limits twice in a row, then PopupLeft and PopupTop are already equal to the limit values. As a result, there is nothing to refresh or change in the Window state.

You can toggle two different "override values" to move the Window back every time:

    async Task LeftChangedHandler(string left)
    {
        float _left = float.Parse(left.Replace("px", ""));

        if (_left < 0)
            left = PopupLeft == "0px" ? "1px" : "0px";
        else if (_left > 200)
            left = PopupLeft == "200px" ? "199px" : "200px";

        PopupLeft = left;
        await DelayedRender();
    }

    async Task TopChangedHandler(string top)
    {
        float _top = float.Parse(top.Replace("px", ""));

        if (_top < 0)
            top = PopupTop == "0px" ? "1px" : "0px";
        else if (_top > 350)
            top = PopupTop == "350px" ? "349px" : "350px";

        PopupTop = top;
        await DelayedRender();
    }

Regards,
Dimo
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.

Victor
Posted on: 22 Feb 2022 13:52

well 2way would deny me the opportunity to implement the changed event where I'd restrict movement based on the dimensions provided by ResizeListener.

 

Getting back to Doug's code, I put a version here in REPL:

https://blazorrepl.telerik.com/wmOwwQbH45n7QQ4n54

 

You'll notice you can drag beyond one red line and it will spring back every time.

But if you drag beyond both the bottom+right red lines, then it will only spring back the first time.

ADMIN
Dimo
Posted on: 22 Feb 2022 07:13

Hello Victor,

Please use two-way binding or a Changed handler for both parameters - Top and Left.

When I replaced Top="100px" with @bind-Top="@PopupTop", the REPL test page started working.

Regards,
Dimo
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Victor
Posted on: 21 Feb 2022 15:40

Not sure if this used to work, but it doesn't now on WASM6 + Telerik3.

I can drag the window to (1001,601) and it springs back to (1000,600).  Yay!

A 2nd attempt does nothing.  Boo!  Dragging it back within bounds does reset the behavior, though it again will only spring back on the first violation.

This issues only fails if both x+y are exceeded.

 

I can reproduce the issue with a window anchored to the left...

https://blazorrepl.telerik.com/QQOmwvPz31JSXC7n07

 

Simply removing this attribute ...

Top="100px"

... fixes it

ADMIN
Marin Bratanov
Posted on: 21 Mar 2021 15:20

Hi Doug,

For latencies as high as 200ms, I can suggest you consider the WebAssembly flavor. You can read more about the problems latency introduces here.

I can also suggest you optimize this a little - keep track of the window size as it resizes (hook to window.resize, e.g., through packages like this one) and with that the view model will know the browser size - the user can't simultaneously move the window and resize the browser anyway. With this, you can eliminate the need to query the browser on each event call.

Regards,
Marin Bratanov
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Doug
Posted on: 20 Mar 2021 01:11
This method mostly works but it does have one issue. In your handler methods if you have to call out to JavaScript or whatever else that takes a little time, and you move the window twice in quick succession the window will bounce back to its original location and then bounce to where it's supposed to be. Running locally through debug it's not that much of an issue but in a deployed scenario where everything is going across the pipe it's more exaggerated. To recreate it you can add "await Task.Delay(200);" to your handler methods before setting the top and left values. You can increase the number of milliseconds to make the issue easier to recreate locally. This isn't a major issue but I think some of my users may have a pretty slow connection so it might become more exaggerated when we go live.