Skip to content

Commit ebbd695

Browse files
authored
[4.1] docs(fileselect,upload): Document methods (#1326)
* docs(fileselect,upload): Document methods * add KB for non-working method in Safari
1 parent ccc4c96 commit ebbd695

File tree

3 files changed

+167
-7
lines changed

3 files changed

+167
-7
lines changed

components/fileselect/overview.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,41 @@ The following table lists the FileSelect parameters. Also check the [FileSelect
8787
| `Multiple` | `bool`<br />(`true`) | Sets if the user can select several files at the same time. |
8888

8989

90+
## FileSelect Reference and Methods
91+
92+
The File Select exposes methods for programmatic operation. To use them, define a reference to the component instance with the `@ref` attribute (example below). The FileSelect methods are:
93+
94+
| Method | Description |
95+
| --- | --- |
96+
| `ClearFiles` | Clears all files from the list. |
97+
| `OpenSelectFilesDialog` | Shows the browser's file selection dialog. This method [doesn't work in Safari due to browser security restrictions]({%slug upload-kb-openselectfilesdialog-safari%}). |
98+
99+
>caption Get reference to the FileSelect and execute methods
100+
101+
````CSHTML
102+
<p>
103+
<TelerikButton OnClick="@SelectFiles">Open File Selection Dialog</TelerikButton>
104+
<TelerikButton OnClick="@Clear">Clear File List</TelerikButton>
105+
</p>
106+
107+
<TelerikFileSelect @ref="@FileSelectRef" />
108+
109+
@code {
110+
private TelerikFileSelect FileSelectRef { get; set; }
111+
112+
private void SelectFiles()
113+
{
114+
FileSelectRef.OpenSelectFilesDialog();
115+
}
116+
117+
private void Clear()
118+
{
119+
FileSelectRef.ClearFiles();
120+
}
121+
}
122+
````
123+
124+
90125
## Next Steps
91126

92127
* [Explore FileSelect Validation]({%slug fileselect-validation%})

components/upload/overview.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,17 @@ The following table lists the Upload parameters. Also check the [Upload API Refe
215215

216216
The Upload exposes methods for programmatic operation. To use them, define a reference to the component instance with the `@ref` attribute (example below). The Upload methods are:
217217

218-
* `ClearFiles` - Clears all files from the list, both uploaded and in queue.
219-
* `UploadFiles` - Uploads all valid selected files. Fires the [OnUpload]({%slug upload-events%}#onupload) event.
220-
* `OpenFileSelectAsync` - Triggers the browser's file select dialog.
218+
| Method | Description |
219+
| --- | --- |
220+
| `ClearFiles` | Clears all files from the list, both uploaded and in queue. |
221+
| `OpenSelectFilesDialog` | Shows the browser's file selection dialog. This method [doesn't work in Safari due to browser security restrictions]({%slug upload-kb-openselectfilesdialog-safari%}). |
222+
| `UploadFiles` | Uploads all valid selected files. Fires the [OnUpload]({%slug upload-events%}#onupload) event. |
221223

222-
>caption Get a reference to the Upload and execute methods.
224+
>caption Get reference to the Upload and execute methods
223225
224226
<div class="skip-repl"></div>
225227

226-
````HTML
228+
````CSHTML
227229
<p>
228230
<TelerikButton OnClick="@SelectFiles">Open File Selection Dialog</TelerikButton>
229231
<TelerikButton OnClick="@Clear">Clear File List</TelerikButton>
@@ -238,9 +240,9 @@ The Upload exposes methods for programmatic operation. To use them, define a ref
238240
@code {
239241
private TelerikUpload UploadRef { get; set; }
240242
241-
private async Task SelectFiles()
243+
private void SelectFiles()
242244
{
243-
await UploadRef.OpenFileSelectAsync();
245+
UploadRef.OpenSelectFilesDialog();
244246
}
245247
246248
private void Clear()
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
title: OpenSelectFilesDialog Doesn't Work in Safari
3+
description: Why the FileSelect and Upload OpenSelectFilesDialog method doesn't work in Safari due to browser security restrictions.
4+
type: troubleshooting
5+
page_title: FileSelect and Upload OpenSelectFilesDialog Method Doesn't Work in Safari
6+
slug: upload-kb-openselectfilesdialog-safari
7+
position:
8+
tags: telerik, blazor, fileselect, upload
9+
ticketid:
10+
res_type: kb
11+
---
12+
13+
## Environment
14+
15+
<table>
16+
<tbody>
17+
<tr>
18+
<td>Product</td>
19+
<td>
20+
FileSelect for Blazor, <br />
21+
Upload for Blazor
22+
</td>
23+
</tr>
24+
<tr>
25+
<td>Browser</td>
26+
<td>Safari</td>
27+
</tr>
28+
</tbody>
29+
</table>
30+
31+
32+
## Description
33+
34+
The `OpenSelectFilesDialog` method of the FileSelect and Upload components doesn't work in Safari. Normally, the browser should pop its native file selection dialog. In Safari, this browser dialog doesn't show when the application tries to open it programmatically via C#.
35+
36+
## Cause\Possible Cause(s)
37+
38+
The `OpenSelectFilesDialog` method is pretty simple. It uses `JSInterop` to call the `click` JavaScript method of the `<input type="file" />` element inside the component HTML output.
39+
40+
Safari requires the file input dialog to open programmatically as a direct result of a user action. If the file input is clicked programmatically, this must happen in JavaScript code, which handles a user event.
41+
42+
JSInterop cannot be directly associated with a user action, due to its nature. A .NET method itself is not directly triggered by user action. For example, an `@onclick` Blazor handler will react to the `click` user event and call a .NET handler. However, the subsequent server-client JSInterop call that executes JavaScript code will no longer have relationship with the user action that started the whole sequence.
43+
44+
The following example demonstrates the described phenomenon without Telerik UI for Blazor components.
45+
46+
>caption File Input Security in Safari
47+
48+
````CSHTML
49+
@inject IJSRuntime js
50+
51+
<p><input type="file" id="fileInput" /></p>
52+
53+
<p>
54+
<button onclick="openFileSelect()">Open File Dialog (JavaScript)</button>
55+
<button @onclick="@OpenFileSelectCS">Open File Dialog (JSInterop)</button>
56+
</p>
57+
58+
@* Move JavaScript code to separate JS files in production apps *@
59+
<script suppress-error="BL9992">//
60+
function openFileSelect() {
61+
var input = document.querySelector("#fileInput");
62+
input.focus();
63+
input.click();
64+
}
65+
//</script>
66+
67+
@code {
68+
private async Task OpenFileSelectCS()
69+
{
70+
await js.InvokeVoidAsync("openFileSelect");
71+
}
72+
}
73+
````
74+
75+
76+
## Suggested Workarounds
77+
78+
The only possible way to open a FileSelect or Upload dialog programmatically is to use pure JavaScript and a user (client-side) event. The dialog opening call must have direct relationship to a user action, for example a button click. So, [attach the event handler with JavaScript](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener), instead of a Blazor directive such as `@onclick`.
79+
80+
>caption Open FileSelect or Upload programmatically in Safari
81+
82+
````CSHTML
83+
@inject IJSRuntime js
84+
85+
<p>
86+
<TelerikButton Id="@ButtonId">Open File Dialog</TelerikButton>
87+
</p>
88+
89+
<TelerikFileSelect Id="@FileSelectId" />
90+
91+
@* Move JavaScript code to separate JS files in production apps *@
92+
<script suppress-error="BL9992">//
93+
function attachClickHandler(buttonId, fileInputId) {
94+
var button = document.getElementById(buttonId);
95+
var fileInput = document.getElementById(fileInputId);
96+
if (button && fileInput) {
97+
button.addEventListener("click", function(e) {
98+
fileInput.click();
99+
});
100+
}
101+
}
102+
//</script>
103+
104+
@code {
105+
private string ButtonId { get; set; } = "button-id";
106+
107+
private string FileSelectId { get; set; } = "fileselect-id";
108+
109+
protected override async Task OnAfterRenderAsync(bool firstRender)
110+
{
111+
if (firstRender)
112+
{
113+
await js.InvokeVoidAsync("attachClickHandler", ButtonId, FileSelectId);
114+
}
115+
await base.OnAfterRenderAsync(firstRender);
116+
}
117+
}
118+
````
119+
120+
## See Also
121+
122+
* [FileSelect Component]({%slug fileselect-overview%})
123+
* [Upload Component]({%slug upload-overview%})

0 commit comments

Comments
 (0)