Skip to content

Commit d8fae76

Browse files
authored
docs(Form): Improve Form UI refresh information and example (#2793)
1 parent 6c5256a commit d8fae76

File tree

1 file changed

+108
-32
lines changed

1 file changed

+108
-32
lines changed

components/form/formitems/overview.md

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -122,58 +122,103 @@ When the user changes a value in a non-template Form item, the other Form items
122122

123123
In such cases, there are a few ways to trigger re-rendering and UI refresh inside or outside the Form:
124124

125-
* Use a Telerik input component inside a [Form item `<Template>`](slug:form-formitems-template).
125+
* Use a Telerik input component inside a [Form item `<Template>`](slug:form-formitems-template). Define two-way binding for the `Value` parameter, or use `Value`, `ValueChanged`, and `ValueExpression`.
126+
* Use a custom component with two-way parameter binding for the respective Form model property. Alternatively, use one-way binding, but implement an `EventCallback` that updates the model property value.
126127
* Call the [`Refresh()` method of the Form](slug:form-overview#form-reference-and-methods). The method will re-render the Form itself.
127128
* Subscribe to the [`OnUpdate` event of the Form](slug:form-events#onupdate). The event is an `EventCallback`, so it will update the whole Razor component, which holds the Form.
128129
* Call `StateHasChanged()` inside the Razor component, which holds the Form. This will re-render the whole Razor component, including the Form.
129130

131+
The example below demonstrates all of the above options. Note the differences in the two custom components:
132+
133+
* `ChildTwo.razor` supports two-way binding with an `EventCallback` for its `Value` parameter.
134+
* `ChildOne.razor` does not support two-way binding and uses an `Action` instead of an `EventCallback`.
135+
130136
>caption How to re-render all Form Items or the Form's parent component
131137
132138
<div class="skip-repl"></div>
133139

134140
````RAZOR Home.razor
141+
@using System.ComponentModel.DataAnnotations
142+
135143
<p>Type in the Form textboxes and observe the different results.</p>
136144
137145
<p>
138-
<label>
146+
<label class="k-checkbox-label">
139147
<TelerikCheckBox @bind-Value="@ShouldUseOnUpdate" />
140-
Use the <strong>Form <code>OnUpdate</code> event (an <code>EventCallback</code>)</strong> to re-render inside and outside the Form
148+
Use the <strong>Form &nbsp;<code>OnUpdate</code>&nbsp; event (an &nbsp;<code>EventCallback</code>)</strong> to
149+
re-render inside and outside the Form
141150
</label>
142151
</p>
143152
144153
<TelerikForm @ref="@FormRef"
145154
Model="@Employee"
146155
OnUpdate="@OnFormUpdate">
156+
<FormValidation>
157+
<DataAnnotationsValidator />
158+
</FormValidation>
147159
<FormItems>
148-
<FormItem Field="@nameof(Person.Name)" LabelText="Regular FormItem - no re-render without OnUpdate"></FormItem>
149-
<FormItem>
160+
<FormItem Field="@nameof(Person.Name)" LabelText="No Template - no re-render without OnUpdate." />
161+
<FormItem Field="@nameof(Person.Name)">
150162
<Template>
151-
<label class="k-label k-form-label" style="color:var(--kendo-color-success)">
152-
FormItem with &nbsp;<code>&lt;Template&gt;</code>&nbsp; - re-render inside and outside the Form</label>
163+
<label class="k-label k-form-label" style="color: var(--kendo-color-success)">
164+
Telerik component - re-render inside and outside the Form.
165+
</label>
153166
<div class="k-form-field-wrap">
154167
<TelerikTextBox @bind-Value="@Employee.Name" DebounceDelay="0" />
168+
<TelerikValidationMessage For="@( () => Employee.Name )" />
169+
</div>
170+
</Template>
171+
</FormItem>
172+
<FormItem Field="@nameof(Person.Name)">
173+
<Template>
174+
<label class="k-label k-form-label" style="color: var(--kendo-color-success)">
175+
Custom component with two-way binding - re-render inside and outside the Form.
176+
</label>
177+
<div class="k-form-field-wrap">
178+
<ChildTwo @bind-Value="@Employee.Name" />
179+
<TelerikValidationMessage For="@( () => Employee.Name )" />
180+
</div>
181+
</Template>
182+
</FormItem>
183+
<FormItem Field="@nameof(Person.Name)">
184+
<Template>
185+
<label class="k-label k-form-label" style="color: var(--kendo-color-success)">
186+
Custom component with one-way binding and EventCallback -
187+
re-render inside and outside the Form.
188+
</label>
189+
<div class="k-form-field-wrap">
190+
<ChildTwo Value="@Employee.Name"
191+
ValueChanged="@OnChildTwoChange_EventCallback"
192+
ValueExpression="@( () => Employee.Name )" />
193+
<TelerikValidationMessage For="@( () => Employee.Name )" />
155194
</div>
156195
</Template>
157196
</FormItem>
158-
<FormItem>
197+
<FormItem Field="@nameof(Person.Name)">
159198
<Template>
160-
<label class="k-label k-form-label" style="color:var(--kendo-color-warning)">
161-
FormItem with Template and Form &nbsp;<code>Refresh()</code>&nbsp; - re-render inside the Form</label>
199+
<label class="k-label k-form-label" style="color: var(--kendo-color-warning)">
200+
Custom component with one-way binding and Form &nbsp;<code>Refresh()</code>&nbsp; -
201+
re-render inside the Form.
202+
</label>
162203
<div class="k-form-field-wrap">
163-
<ChildComponent Value="@Employee.Name"
164-
ValueExpression="@( () => Employee.Name )"
165-
OnChange="@OnChildChange_Refresh" />
204+
<ChildOne Value="@Employee.Name"
205+
ValueExpression="@( () => Employee.Name )"
206+
OnChange="@OnChildOneChange_Refresh" />
207+
<TelerikValidationMessage For="@( () => Employee.Name )" />
166208
</div>
167209
</Template>
168210
</FormItem>
169-
<FormItem>
211+
<FormItem Field="@nameof(Person.Name)">
170212
<Template>
171-
<label class="k-label k-form-label" style="color:var(--kendo-color-tertiary)">
172-
FormItem with Template and &nbsp;<code>StateHasChanged()</code>&nbsp; - re-render inside and outside the Form</label>
213+
<label class="k-label k-form-label" style="color: var(--kendo-color-tertiary)">
214+
Custom component with one-way binding and &nbsp;<code>StateHasChanged()</code>&nbsp; -
215+
re-render inside and outside the Form.
216+
</label>
173217
<div class="k-form-field-wrap">
174-
<ChildComponent Value="@Employee.Name"
175-
ValueExpression="@( () => Employee.Name )"
176-
OnChange="@OnChildChange_StateHasChanged" />
218+
<ChildOne Value="@Employee.Name"
219+
ValueExpression="@( () => Employee.Name )"
220+
OnChange="@OnChildOneChange_StateHasChanged" />
221+
<TelerikValidationMessage For="@( () => Employee.Name )" />
177222
</div>
178223
</Template>
179224
</FormItem>
@@ -182,7 +227,7 @@ In such cases, there are a few ways to trigger re-rendering and UI refresh insid
182227
183228
<br />
184229
185-
<p><code>Employee.Name</code> in UI outside the Form: <strong>@Employee.Name</strong></p>
230+
<p>&nbsp;<code>Employee.Name</code>&nbsp; in UI outside the Form: <strong>@Employee.Name</strong></p>
186231
187232
<TelerikButton OnClick="@( () => { } )"
188233
ButtonType="@ButtonType.Button">
@@ -192,7 +237,7 @@ In such cases, there are a few ways to trigger re-rendering and UI refresh insid
192237
@code {
193238
private TelerikForm? FormRef { get; set; }
194239
195-
private Person Employee = new Person();
240+
private Person Employee { get; set; } = new();
196241
197242
private bool ShouldUseOnUpdate { get; set; }
198243
@@ -207,18 +252,22 @@ In such cases, there are a few ways to trigger re-rendering and UI refresh insid
207252
// of the whole Razor component, which holds the Form.
208253
}
209254
210-
private void OnChildChange_Refresh(string newValue)
255+
private void OnChildTwoChange_EventCallback(string newValue)
256+
{
257+
Employee.Name = newValue;
258+
}
259+
260+
private void OnChildOneChange_Refresh(string newValue)
211261
{
212262
Employee.Name = newValue;
213263
214264
if (!ShouldUseOnUpdate)
215265
{
216266
FormRef?.Refresh();
217267
}
218-
219268
}
220269
221-
private void OnChildChange_StateHasChanged(string newValue)
270+
private void OnChildOneChange_StateHasChanged(string newValue)
222271
{
223272
Employee.Name = newValue;
224273
@@ -228,15 +277,9 @@ In such cases, there are a few ways to trigger re-rendering and UI refresh insid
228277
}
229278
}
230279
231-
protected override void OnInitialized()
232-
{
233-
Employee = new Person();
234-
235-
base.OnInitialized();
236-
}
237-
238280
public class Person
239281
{
282+
[Required]
240283
public string Name { get; set; }
241284
242285
public Person()
@@ -246,7 +289,40 @@ In such cases, there are a few ways to trigger re-rendering and UI refresh insid
246289
}
247290
}
248291
````
249-
````RAZOR ChildComponent.razor
292+
````RAZOR ChildTwo.razor
293+
@using System.Linq.Expressions
294+
295+
<TelerikTextBox Value="@Value"
296+
ValueChanged="@TextBoxValueChanged"
297+
ValueExpression="@ValueExpression"
298+
DebounceDelay="0" />
299+
300+
@code {
301+
[Parameter]
302+
public string Value { get; set; } = string.Empty;
303+
304+
// This parameter is an EventCallback.
305+
// It will refresh the whole parent component's UI.
306+
[Parameter]
307+
public EventCallback<string> ValueChanged { get; set; }
308+
309+
// Get a validation expression from a parent component.
310+
// See https://www.telerik.com/blazor-ui/documentation/knowledge-base/inputs-validation-child-component
311+
[Parameter]
312+
public Expression<Func<string>>? ValueExpression { get; set; }
313+
314+
private async Task TextBoxValueChanged(string newValue)
315+
{
316+
Value = newValue;
317+
318+
if (ValueChanged.HasDelegate)
319+
{
320+
await ValueChanged.InvokeAsync(newValue);
321+
}
322+
}
323+
}
324+
````
325+
````RAZOR ChildOne.razor
250326
@using System.Linq.Expressions
251327
252328
<TelerikTextBox Value="@Value"

0 commit comments

Comments
 (0)