Skip to content

Commit d18df31

Browse files
Merge pull request #7058 from syncfusion-content/985195-Merge-cp3
Added missing files
2 parents c8e23ce + b1b2b66 commit d18df31

File tree

7 files changed

+683
-20
lines changed

7 files changed

+683
-20
lines changed
21.4 KB
Loading

blazor/chat-ui/speech-to-text.md

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
---
2+
layout: post
3+
title: Speech-to-Text with Blazor Chat UI Component | Syncfusion
4+
description: Checkout and learn about Speech-to-Text configuration with Blazor Chat UI component in Blazor Server App and Blazor WebAssembly App.
5+
platform: Blazor
6+
control: Chat UI
7+
documentation: ug
8+
---
9+
10+
# Speech-to-Text in Blazor Chat UI
11+
12+
The Syncfusion Blazor Chat UI component integrates `Speech-to-Text` functionality through the browser's [Web Speech API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Speech_API). This enables the conversion of spoken words into text using the device's microphone, allowing users to interact with the Chat UI through voice input.
13+
14+
## Configure Speech-to-Text
15+
16+
To enable Speech-to-Text functionality in the Blazor Chat UI component, update the `Home.razor` file to incorporate the Web Speech API.
17+
18+
The [SpeechToText](https://blazor.syncfusion.com/documentation/speech-to-text/getting-started-web-app) component listens to audio input from the device’s microphone, transcribes spoken words into text, and updates the Chat UI’s editable footer using the [FooterTemplate](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.InteractiveChat.SfChatUI.html#Syncfusion_Blazor_InteractiveChat_SfChatUI_FooterTemplate) tag directive to display the transcribed text. Once the transcription appears in the footer, users can send it as a message to others.
19+
20+
### Configuration Options
21+
22+
* **[`Language`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Inputs.SfSpeechToText.html#Syncfusion_Blazor_Inputs_SfSpeechToText_Language)**: Specifies the language for speech recognition. For example:
23+
24+
* `en-US` for American English
25+
* `fr-FR` for French
26+
27+
* **[`AllowInterimResults`](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Inputs.SfSpeechToText.html#Syncfusion_Blazor_Inputs_SfSpeechToText_AllowInterimResults)**: Set to `true` to receive real-time (interim) recognition results, or `false` to receive only final results.
28+
29+
The `speechtotext.js` file handles operations related to the content of the editable footer, such as checking for meaningful input, clearing existing text, and updating the content with the transcribed value. Meanwhile, the `speechtotext.css` file styles the Chat UI layout and ensures the component remains responsive across different screen sizes and devices.
30+
31+
{% tabs %}
32+
{% highlight c# tabtitle="razor" %}
33+
34+
@using Syncfusion.Blazor.InteractiveChat
35+
@using Syncfusion.Blazor.Buttons
36+
@using Syncfusion.Blazor.Inputs
37+
@inject IJSRuntime JSRuntime
38+
39+
<div class="integration-speechtotext">
40+
<SfChatUI @ref="chatUI" ID="chatUser" AutoScrollToBottom=true User="CurrentUserModel" Messages="ChatUserMessages">
41+
<FooterTemplate>
42+
<div class="e-footer-wrapper">
43+
<div id="chatui-footer" class="content-editor" contenteditable="true" placeholder="Click to speak or start typing..." @oninput="@UpdateContent" @onkeydown="@OnKeyDown" @ref="@EditableDiv">@ChatUIFooterValue</div>
44+
<div class="option-container">
45+
<SfSpeechToText ID="speechToText" TranscriptChanging="@OnTranscriptChange" SpeechRecognitionStopped="@HandleStopRecognition"
46+
CssClass="@($"e-flat {SpeechToTextCssClass}")" Disabled="@DisabledState"></SfSpeechToText>
47+
<SfButton ID="chatui-sendButton" IconCss="e-assist-send e-icons" CssClass="@ButtonCssClass" @onclick="SendButtonClicked"></SfButton>
48+
</div>
49+
</div>
50+
</FooterTemplate>
51+
</SfChatUI>
52+
</div>
53+
@code {
54+
private SfChatUI chatUI;
55+
private static UserModel CurrentUserModel = new UserModel() { ID = "User1", User = "Albert" };
56+
private static UserModel MichaleUserModel = new UserModel() { ID = "User2", User = "Michale Suyama" };
57+
private string ChatUIFooterValue = String.Empty;
58+
private ElementReference EditableDiv;
59+
private string FooterContent = String.Empty;
60+
private string SpeechToTextCssClass = "visible";
61+
private string ButtonCssClass = String.Empty;
62+
private bool DisabledState = false;
63+
64+
private List<ChatMessage> ChatUserMessages = new List<ChatMessage>()
65+
{
66+
new ChatMessage() { Text = "Hi Michale, are we on track for the deadline?", Author = CurrentUserModel },
67+
new ChatMessage() { Text = "Yes, the design phase is complete.", Author = MichaleUserModel },
68+
new ChatMessage() { Text = "I’ll review it and send feedback by today.", Author = CurrentUserModel }
69+
};
70+
71+
private async void OnTranscriptChange(TranscriptChangeEventArgs args)
72+
{
73+
ChatUIFooterValue = args.Transcript;
74+
await JSRuntime.InvokeVoidAsync("updateContentEditableDiv", EditableDiv, ChatUIFooterValue);
75+
await InvokeAsync(StateHasChanged);
76+
}
77+
private async Task UpdateContent()
78+
{
79+
FooterContent = await JSRuntime.InvokeAsync<String>("isFooterContainsValue", EditableDiv);
80+
ToggleVisibility();
81+
}
82+
private async Task HandleStopRecognition()
83+
{
84+
FooterContent = ChatUIFooterValue;
85+
ToggleVisibility();
86+
await InvokeAsync(StateHasChanged);
87+
}
88+
private void ToggleVisibility()
89+
{
90+
ButtonCssClass = string.IsNullOrWhiteSpace(FooterContent) ? "" : "visible";
91+
SpeechToTextCssClass = string.IsNullOrWhiteSpace(FooterContent) ? "visible" : "";
92+
}
93+
94+
private async Task SendButtonClicked()
95+
{
96+
chatUI.Messages.Add(new ChatMessage() { Text = FooterContent, Author = CurrentUserModel });
97+
ChatUIFooterValue = String.Empty;
98+
await JSRuntime.InvokeVoidAsync("emptyFooterValue", EditableDiv);
99+
await UpdateContent();
100+
ToggleVisibility();
101+
}
102+
private async Task OnKeyDown(KeyboardEventArgs e)
103+
{
104+
if (e.Key == "Enter" && !e.ShiftKey)
105+
{
106+
await SendButtonClicked();
107+
}
108+
}
109+
}
110+
111+
{% endhighlight %}
112+
113+
{% highlight c# tabtitle="speechtotext.js" %}
114+
115+
// Checks if the content editable element contains meaningful text and cleans up.
116+
function isFooterContainsValue(elementref) {
117+
if (!elementref.innerText.trim() !== '') {
118+
if ((elementref.innerHTML === '<br>' || elementref.innerHTML.trim() === '')) {
119+
elementref.innerHTML = '';
120+
}
121+
}
122+
return elementref.innerText || "";
123+
}
124+
// Clears the text content of a content editable element.
125+
function emptyFooterValue(elementref) {
126+
if (elementref) {
127+
elementref.innerText = "";
128+
}
129+
}
130+
// Updates the text content of a content editable element with a specified value.
131+
function updateContentEditableDiv(element, value) {
132+
if (element) {
133+
element.innerText = value;
134+
}
135+
}
136+
137+
{% endhighlight %}
138+
139+
{% highlight c# tabtitle="speechtotext.css" %}
140+
141+
.integration-speechtotext {
142+
height: 400px;
143+
width: 450px;
144+
margin: 0 auto;
145+
}
146+
147+
.integration-speechtotext #chatui-sendButton {
148+
width: 40px;
149+
height: 40px;
150+
font-size: 15px;
151+
border: none;
152+
background: none;
153+
cursor: pointer;
154+
}
155+
156+
.integration-speechtotext #speechToText.visible,
157+
.integration-speechtotext #chatui-sendButton.visible {
158+
display: inline-block;
159+
}
160+
161+
.integration-speechtotext #speechToText,
162+
.integration-speechtotext #chatui-sendButton {
163+
display: none;
164+
}
165+
166+
@@media only screen and (max-width: 750px) {
167+
.integration-speechtotext {
168+
width: 100%;
169+
}
170+
}
171+
172+
.integration-speechtotext .e-footer-wrapper {
173+
display: flex;
174+
border: 1px solid #c1c1c1;
175+
margin: 5px 5px 0 5px;
176+
border-radius: 10px;
177+
padding: 5px;
178+
}
179+
180+
.integration-speechtotext .content-editor {
181+
width: 100%;
182+
overflow-y: auto;
183+
font-size: 14px;
184+
min-height: 20px;
185+
max-height: 150px;
186+
padding: 10px;
187+
}
188+
189+
.integration-speechtotext .content-editor[contentEditable='true']:empty:before {
190+
content: attr(placeholder);
191+
color: #6b7280;
192+
font-style: italic;
193+
}
194+
195+
.integration-speechtotext .option-container {
196+
align-self: flex-end;
197+
}
198+
199+
{% endhighlight %}
200+
201+
{% endtabs %}
202+
203+
![Integrating Speech-to-Text with Chat UI](./images/chatui-stt.png)
204+
205+
## Error Handling
206+
207+
The `SpeechToText` component provides events to handle errors that may occur during speech recognition. For more information, refer to the [Error Handling](https://blazor.syncfusion.com/documentation/speech-to-text/speech-recognition#error-handling) section in the documentation.
208+
209+
## Browser Compatibility
210+
211+
The `SpeechToText` component relies on the [Speech Recognition API](https://developer.mozilla.org/en-US/docs/Web/API/SpeechRecognition), which has limited browser support. Refer to the [Browser Compatibility](https://blazor.syncfusion.com/documentation/speech-to-text/speech-recognition#browser-support) section for detailed information.
212+
213+
## See Also
214+
215+
* [Messages](./messages)
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
layout: post
3+
title: Form Integration in Blazor File Upload Component | Syncfusion
4+
description: Learn how to integrate the Syncfusion Blazor File Upload component with Blazor's EditForm and DataForm for seamless form-based file management.
5+
platform: Blazor
6+
control: File Upload
7+
documentation: ug
8+
---
9+
10+
# Form Integration in Blazor File Upload Component
11+
12+
The Syncfusion Blazor File Upload component seamlessly integrates with Blazor's [EditForm](https://learn.microsoft.com/en-us/aspnet/core/blazor/forms/?view=aspnetcore-9.0) and the Syncfusion [DataForm](https://blazor.syncfusion.com/documentation/data-form/getting-started-with-web-app), enabling you to build robust forms with file upload functionality. This integration associates the uploaded file information with a data model, leveraging the form's built-in validation.
13+
14+
When a file is selected, its information is added to the model property bound to the component. Upon form submission, the entire model, including the list of selected files, is passed to the submit event handler.
15+
16+
## File Upload with EditForm Integration
17+
18+
Integrating the File Upload component into a Blazor `EditForm` streamlines data entry by including file management directly within the form.
19+
20+
Validation for the file input is achieved by binding the component to a model property. The [ValueChange](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Inputs.UploaderEvents.html#Syncfusion_Blazor_Inputs_UploaderEvents_ValueChange) and [OnRemove](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.Inputs.UploaderEvents.html#Syncfusion_Blazor_Inputs_UploaderEvents_OnRemove) events are used to update this property with the current list of files. Within these events, it is crucial to call `EditContext.NotifyFieldChanged` to trigger the form's validation logic immediately after the file list changes.
21+
22+
When the form is successfully submitted, the `OnValidSubmit` event handler receives the `EditContext`, which contains the complete form model.
23+
24+
```cshtml
25+
@using System.ComponentModel.DataAnnotations
26+
@using Syncfusion.Blazor.Inputs
27+
@using Syncfusion.Blazor.Buttons
28+
29+
<EditForm Model="@employee" OnValidSubmit="@HandleValidSubmit" Context="formContext">
30+
<DataAnnotationsValidator />
31+
<div class="form-group">
32+
<SfUploader @ref="@UploaderObj" ID="UploadFiles">
33+
<UploaderEvents ValueChange="@(async (args) => await OnChange(args, formContext))" OnRemove="@(async (args) => await OnRemove(args, formContext))"></UploaderEvents>
34+
</SfUploader>
35+
<ValidationMessage For="() => employee.files" />
36+
</div>
37+
<SfButton type="submit" CssClass="e-primary">Submit</SfButton>
38+
</EditForm>
39+
40+
@code {
41+
public class UserDataModel
42+
{
43+
[MinLength(1, ErrorMessage = "Please upload a file")]
44+
public List<FileInfo> files { get; set; } = new();
45+
}
46+
47+
public UserDataModel employee = new UserDataModel();
48+
private SfUploader UploaderObj;
49+
50+
private async Task OnChange(UploadChangeEventArgs args, EditContext context)
51+
{
52+
employee.files = await UploaderObj.GetFilesDataAsync();
53+
context?.NotifyFieldChanged(FieldIdentifier.Create(() => employee.files));
54+
}
55+
56+
private async Task OnRemove(RemovingEventArgs args, EditContext context)
57+
{
58+
var currentFiles = await UploaderObj.GetFilesDataAsync();
59+
var fileToRemove = args.FilesData.FirstOrDefault();
60+
if (fileToRemove != null)
61+
{
62+
currentFiles = currentFiles.Where(f => f.Name != fileToRemove.Name).ToList();
63+
}
64+
employee.files = currentFiles;
65+
context?.NotifyFieldChanged(FieldIdentifier.Create(() => employee.files));
66+
}
67+
68+
public void HandleValidSubmit(EditContext args)
69+
{
70+
// The form model (args.Model) now contains the list of selected files.
71+
// The 'employee.files' property holds the FileInfo objects.
72+
// From here, you can implement custom logic to upload the files to a server,
73+
// for example, by iterating through the list and using HttpClient.
74+
var filesToUpload = employee.files;
75+
// Custom file upload logic goes here.
76+
}
77+
}
78+
```
79+
80+
{% previewsample "https://blazorplayground.syncfusion.com/embed/rXroWjZwIzUqaemW?appbar=false&editor=false&result=true&errorlist=false&theme=bootstrap5" %}
81+
82+
![Blazor File Upload component within an EditForm, showing validation and submission.](./images/blazor-uploader-editform.gif)
83+
84+
## File Upload with DataForm Integration
85+
86+
The File Upload component can also be integrated into a Syncfusion `DataForm` to automatically build a form from a model that includes file upload capabilities.
87+
88+
When the `DataForm` is submitted, the [OnSubmit](https://help.syncfusion.com/cr/blazor/Syncfusion.Blazor.DataForm.SfDataForm.html#Syncfusion_Blazor_DataForm_SfDataForm_OnSubmit) event handler receives the `EditContext`. The `EditContext.Model` property contains the complete form data, including the list of `FileInfo` objects from the File Upload component. This allows you to access and process the file information as part of the form's submission logic.
89+
90+
91+
```cshtml
92+
@using Syncfusion.Blazor.DataForm
93+
@using System.ComponentModel.DataAnnotations
94+
@using Syncfusion.Blazor.Inputs
95+
96+
<SfDataForm ID="MyForm" Model="@UserModel" Width="50%" OnSubmit="Submit" @ref="@DataForm">
97+
<FormValidator>
98+
<DataAnnotationsValidator></DataAnnotationsValidator>
99+
</FormValidator>
100+
<FormItems>
101+
<FormItem Field="@nameof(UserModel.files)">
102+
<Template>
103+
<SfUploader ID="UploadFiles" @ref="@UploaderObj">
104+
<UploaderEvents ValueChange="async (args) => await OnChange(args)" OnRemove="async (args) => await OnRemove(args)"></UploaderEvents>
105+
</SfUploader>
106+
</Template>
107+
</FormItem>
108+
</FormItems>
109+
</SfDataForm>
110+
111+
@code {
112+
public class UserDataModel
113+
{
114+
[MinLength(1, ErrorMessage = "Please upload a file")]
115+
public List<FileInfo> files { get; set; } = new();
116+
}
117+
118+
private UserDataModel UserModel = new UserDataModel();
119+
private SfDataForm DataForm;
120+
private SfUploader UploaderObj;
121+
122+
private async Task OnChange(UploadChangeEventArgs args)
123+
{
124+
this.UserModel.files = await UploaderObj.GetFilesDataAsync();
125+
var fieldIdentifier = FieldIdentifier.Create(() => UserModel.files);
126+
DataForm.EditContext?.NotifyFieldChanged(fieldIdentifier);
127+
}
128+
129+
private async Task OnRemove(RemovingEventArgs args)
130+
{
131+
var currentFiles = await UploaderObj.GetFilesDataAsync();
132+
var fileToRemove = args.FilesData.FirstOrDefault();
133+
if (fileToRemove != null)
134+
{
135+
currentFiles = currentFiles.Where(f => f.Name != fileToRemove.Name).ToList();
136+
}
137+
this.UserModel.files = currentFiles; ;
138+
var fieldIdentifier = FieldIdentifier.Create(() => UserModel.files);
139+
DataForm.EditContext?.NotifyFieldChanged(fieldIdentifier);
140+
}
141+
142+
private void Submit(EditContext args)
143+
{
144+
// The form model is available in args.Model.
145+
// The 'files' property contains the list of selected FileInfo objects.
146+
// Custom file upload logic can be implemented here.
147+
var modelWithFileData = (UserDataModel)args.Model;
148+
var filesToUpload = modelWithFileData.files;
149+
}
150+
}
151+
```
152+
153+
{% previewsample "https://blazorplayground.syncfusion.com/embed/LZheWNXGeJtxWIXQ?appbar=false&editor=false&result=true&errorlist=false&theme=bootstrap5" %}
154+
155+
![Blazor File Upload component within a Syncfusion DataForm.](./images/blazor-uploader-dataform.gif)
106 KB
Loading
100 KB
Loading

0 commit comments

Comments
 (0)