I would like to be to allow the user to resize the Blazor Telerik Window component to their individual liking. For example, like a resizable textbox but for a window/modal. I would assume this would function the same way as I would resize a window in Windows OS by dragging the corner or sides of an open window.
I would imagine most applications would use the Alert, Confim, Prompt concepts so it would be nice if they were built in.
It would further be nice if they were styleable and callable from c# code very similar to the wpf.
Of course as a default they could follow whatever css style is being used already.
RadWindow.Alert(text);
RadWindow.Confirm(text, () => {});
RadWindow.Prompt(text, result => {});
https://docs.telerik.com/devtools/wpf/controls/radwindow/features/predefined-dialogs
At the moment, a second modal window does not "block" the first.
For example, a static variable in aTelerik Window class can be used to track the z-index and render the dialog and modal background with increasing values when a new one is shown.
If you have other suggestions on handling the situation, share them below. Also, comment whether you would like that static class/variable to be public so you can set its initial value.
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);
});
}
}
---
I have a Multiselect as an editor in the Grid. When I click in the multiselect the popup with the choices stays hidden behind the window.
<AdminEdit>
Workaround:
You can increase the z-index of the k-animation-container
<style>
.k-animation-container {
z-index: 15000;
}
</style>
<TelerikGrid Data=@MyData EditMode="@GridEditMode.Popup" Pageable="true" Height="300px" OnUpdate="@UpdateHandler">
<GridColumns>
<GridColumn Field=@nameof(SampleData.ID) Editable="false" Title="ID" />
<GridColumn Field=@nameof(SampleData.Name) Title="Name" />
<GridColumn Field=@nameof(SampleData.Roles) Title="Position">
<Template>
@{
var item = context as SampleData;
@if (item.Roles.Any())
{
foreach (var role in item.Roles)
{
<span>@role</span>
}
}
}
</Template>
<EditorTemplate>
@{
CurrentlyEditedEmployee = context as SampleData;
<TelerikMultiSelect @bind-Value="@selectedValues" Data="@CurrentlyEditedEmployee.Roles"></TelerikMultiSelect>
}
</EditorTemplate>
</GridColumn>
<GridCommandColumn>
<GridCommandButton Command="Save" Icon="save" ShowInEdit="true">Update</GridCommandButton>
<GridCommandButton Command="Edit" Icon="edit">Edit</GridCommandButton>
</GridCommandColumn>
</GridColumns>
</TelerikGrid>
@code {
List<SampleData> MyData { get; set; }
List<string> Roles { get; set; }
SampleData CurrentlyEditedEmployee { get; set; }
private List<string> selectedValues { get; set; }
public async Task UpdateHandler(GridCommandEventArgs args)
{
SampleData item = (SampleData)args.Item;
// perform actual data source operations here through your service
await MyService.Update(item);
// update the local view-model data with the service data
await GetGridData();
}
//in a real case, keep the models in dedicated locations, this is just an easy to copy and see example
public class SampleData
{
public int ID { get; set; }
public string Name { get; set; }
public List<string> Roles { get; set; } = new List<string>() { "Test" };
}
async Task GetGridData()
{
MyData = await MyService.Read();
Roles = await MyService.GetRoles();
}
protected override async Task OnInitializedAsync()
{
await GetGridData();
}
// the following static class mimics an actual data service that handles the actual data source
// replace it with your actual service through the DI, this only mimics how the API can look like and works for this standalone page
public static class MyService
{
private static List<SampleData> _data { get; set; } = new List<SampleData>();
private static List<string> Roles = new List<string> { "Manager", "Employee", "Contractor" };
public static async Task<List<SampleData>> Read()
{
if (_data.Count < 1)
{
for (int i = 1; i < 50; i++)
{
_data.Add(new SampleData()
{
ID = i,
Name = "Name " + i.ToString()
});
}
}
return await Task.FromResult(_data);
}
public static async Task<List<string>> GetRoles()
{
return await Task.FromResult(Roles);
}
public static async Task Update(SampleData itemToUpdate)
{
var index = _data.FindIndex(i => i.ID == itemToUpdate.ID);
if (index != -1)
{
_data[index] = itemToUpdate;
}
}
}
}
</AdminEdit>
When you open the Modal Window, try to drag it through a page that has a vertical scrollbar. The Modal Window is moving away from the cursor. This can be seen in our Modal Window demo too. If there is no vertical scrollbar on the page, the Modal Window dragging is working properly.
<div style="height:400px;"></div>
<TelerikButton Icon="window" OnClick=@(()=> WindowVisible = true)>Open Modal</TelerikButton>
<div style="height:400px;"></div>
<TelerikWindow Class="demo-window" Width="500px" Height="300px" Centered="true" @bind-Visible=@WindowVisible Modal="true">
<WindowTitle>
<strong>Modal Window</strong>
</WindowTitle>
<WindowActions>
<WindowAction Name="Close" />
</WindowActions>
<WindowContent>
<p>Click the close button to dismiss this modal dialog.</p>
</WindowContent>
</TelerikWindow>
@code { public bool WindowVisible { get; set; } }
<style type="text/css">
.demo-window {
z-index: 44444;
}
</style>
Reproduction happens in the demo too here: https://demos.telerik.com/blazor-ui/window/modal
When I host a TelerikWindow in a component that is itself hosted in a TelerikWindow the main window does not display.
VS shows continuous, never ending, memory consumption.
This behavior just started with the 2.0.0 release.
When I try to add a context menu to the content in the Modal Window the context menu stays behind the modal.
===
A possible workaround is to increase the z-index of the ContextMenu:
<TelerikContextMenu Data="@MenuItems" Selector="#menu-target"
Class="menu-on-top" />
<style>
.menu-on-top,
.k-animation-container:has(.menu-on-top) {
z-index: 11000 !important;
}
</style>
<TelerikWindow Width="240px" Height="160px"
Top="100px" Left="100px"
Visible="true" Modal="true">
<WindowTitle>Window</WindowTitle>
<WindowContent>
<div style="height:60px;border: 1px solid;"
id="menu-target">Right-click me</div>
</WindowContent>
</TelerikWindow>
@code {
List<ContextMenuItem> MenuItems { get; set; } = new List<ContextMenuItem>();
protected override void OnInitialized()
{
for (int i = 1; i <= 7; i++)
{
MenuItems.Add(new ContextMenuItem() { Text = $"Menu item {i}" });
}
base.OnInitialized();
}
public class ContextMenuItem
{
public string Text { get; set; } = string.Empty;
}
}
The Window-Component provides parameters for setting width and height.
In addition to that, it would be great if parameters for MaxWidth, MaxHeight + MinWidth, MinHeight would be provided.
I'm especially missing a MaxHeight parameter for creating popups that grow with the content (only known at runtime) but do not become larger than the screen.
To make sure that the whole content is reachable by the users I'm setting the Height to 95vh but this leaves white space if there is not enough content to fill the screen.
Regards,
René
Currently, when the window is minimized the content is lost. The content area is detached from the DOM and re-initialized when it is shown again.
<AdminEdit>
Workaround:
You can workaround that issue by creating custom minimize and maximize actions for the window, where you hide the content area with CSS.
Code snippet:
<TelerikWindow Class="@( isMinimized ? "minimize-window" : "maximize-window" )"
Width="500px"
Height="@Height"
Top="40%"
Left="45%"
Visible="true">
<WindowTitle>
<strong>Status</strong>
</WindowTitle>
<WindowActions>
<WindowAction Name="MyCustomMinimize" OnClick="@CustomMinimize" Icon="@IconName.WindowMinimize"></WindowAction>
@if (isMinimized)
{
<WindowAction Name="MyCustomMaximize" OnClick="@CustomMaximize" Icon="@IconName.Window"></WindowAction>
}
<WindowAction Name="Close"></WindowAction>
</WindowActions>
<WindowContent>
<form class="k-form">
<fieldset class="k-form-fieldset">
<legend class="k-form-legend">User Details</legend>
<label class="k-form-field">
<span>First Name</span>
<input class="k-textbox" placeholder="Your Name" />
</label>
<label class="k-form-field">
<span>Last Name</span>
<input class="k-textbox" placeholder="Your Last Name" />
</label>
</fieldset>
</form>
</WindowContent>
</TelerikWindow>
@code {
public bool isMinimized { get; set; }
public string Height { get; set; } = "350px";
private void CustomMinimize()
{
isMinimized = true;
Height = "auto";
}
private void CustomMaximize()
{
isMinimized = false;
Height = "350px";
}
}
<style>
.minimize-window .k-content {
display: none;
padding: 0px !important;
}
.maximize-window .k-content {
display: block;
padding: 16px 16px;
}
</style>
</AdminEdit>
When a Window is declared inside the Content of another Window, the child Window is resized twice the dragged size.
Reproduction: https://blazorrepl.telerik.com/wwahOtEt49vtoFbZ39.
Steps to reproduce:
The behavior occurs when the child Window contains a component. However, it is not applicable for all components. For example, placing a TextBox or simple text in the child Window does not seem to cause an issue.
I'm working on blazor server side application.
After update Telerik.UI.for.Blazor from 2.1 to 2.5 (before I
updated .net core from 3.0 to 3.1) it shows following error:
InvalidOperationException: The current thread is not associated
with the Dispatcher. Use InvokeAsync() to switch execution to the Dispatcher
when triggering rendering or component state.
I investigated that it's cause by Telerik window.
The error occurs when window is on start page or when the
page is refreshed.
Below code for Index.razor which cause the error:
@page "/"
<
TelerikWindow
@
bind-Visible
=
"@WindowIsVisible"
>
<
WindowTitle
>
<
strong
>The Title</
strong
>
</
WindowTitle
>
<
WindowContent
>
This is my window <
strong
>popup</
strong
> content.
</
WindowContent
>
<
WindowActions
>
<
WindowAction
Name
=
"Minimize"
></
WindowAction
>
<
WindowAction
Name
=
"Maximize"
></
WindowAction
>
<
WindowAction
Name
=
"Close"
></
WindowAction
>
</
WindowActions
>
</
TelerikWindow
>
<
TelerikButton
OnClick="@( () => WindowIsVisible = !WindowIsVisible )">Toggle window</
TelerikButton
>
@code {
bool WindowIsVisible { get; set; } = false;
}
Consider a scenario with two Windows. The first one is centered. Users open a second Window from the first one, and the second Window gains focus.
At this point, if the user clicks on the titlebar of the first Window, it will lose its centered position and move to the corner of the screen.
Here is a REPL test page: https://blazorrepl.telerik.com/wSOMEtEL55Ddk4v441
A possible workaround is to set explicit Width, Height, Top and Left values to the first Window, so that it's not centered, but appears to be: https://blazorrepl.telerik.com/QeaWuNus07TfnCz731