Day 6: Advanced Components
Learn parent-child component communication, lifecycle methods, and cascading values.
1. Component Parameters
Pass data from a parent component to a child component using parameters.
Example: Parent ➔ Child Communication
ParentComponent.razor
@page "/parent"
<h3>Parent Component</h3>
<ChildComponent Title="Hello from Parent!" />
ChildComponent.razor
<h4>@Title</h4>
@code {
[Parameter]
public string Title { get; set; } // Receives data from parent
}
2. Child ➔ Parent Communication with EventCallback
Child components can notify parents of events (e.g., button clicks).
Example: Child Emits Event
ChildComponent.razor
<button @onclick="NotifyParent">Click Me</button>
@code {
[Parameter]
public EventCallback OnChildClicked { get; set; }
private async Task NotifyParent() => await OnChildClicked.InvokeAsync();
}
ParentComponent.razor
@page "/parent"
<ChildComponent OnChildClicked="HandleChildClick" />
<p>Clicked count: @clickCount</p>
@code {
private int clickCount = 0;
private void HandleChildClick() => clickCount++;
}
3. Component Lifecycle Methods
Key lifecycle methods for components:
| Method | When It Runs |
OnInitialized | After component is initialized |
OnInitializedAsync | Async version of OnInitialized |
OnParametersSet | After parent sets parameters |
OnAfterRender | After component renders |
Example: Fetch Data on Initialization
@page "/users"
@inject HttpClient Http
@if (users == null)
{
<p>Loading...</p>
}
else
{
<ul>
@foreach (var user in users)
{
<li>@user.Name</li>
}
</ul>
}
@code {
private List<User> users;
protected override async Task OnInitializedAsync()
{
// Fetch data when component initializes
users = await Http.GetFromJsonAsync<List<User>>("/api/users");
}
}
4. Cascading Values
Pass values to deeply nested components without explicit parameters.
Example: Theme Settings
ParentComponent.razor
@page "/parent"
<CascadingValue Value="@theme">
<ChildComponent />
</CascadingValue>
@code {
private string theme = "dark-mode";
}
ChildComponent.razor
<h4>Current Theme: @Theme</h4>
@code {
[CascadingParameter]
public string Theme { get; set; } // Automatically gets value from ancestor
}
5. Practice Task
Create a TodoList Component:
Parent component holds a list of todos.
Child component (
TodoItem) displays a todo and emits an event when marked as done.Use
EventCallbackto notify the parent to remove the todo.
Solution:
ParentComponent.razor
@page "/todos"
<h3>Todos</h3>
@foreach (var todo in todos)
{
<TodoItem
Todo="@todo"
OnTodoDone="@(() => RemoveTodo(todo.Id))" />
}
@code {
private List<Todo> todos = new()
{
new Todo { Id = 1, Text = "Learn Blazor" },
new Todo { Id = 2, Text = "Build a project" }
};
private void RemoveTodo(int id) => todos.RemoveAll(t => t.Id == id);
}
TodoItem.razor
<div class="todo-item">
<input type="checkbox" @onchange="MarkAsDone" />
@Todo.Text
</div>
@code {
[Parameter]
public Todo Todo { get; set; }
[Parameter]
public EventCallback OnTodoDone { get; set; }
private async Task MarkAsDone() => await OnTodoDone.InvokeAsync();
}
6. Common Issues (For Beginners)
Parameter Name Mismatch: Ensure parent and child parameter names match.
Missing
InvokeAsync: Always callInvokeAsyncforEventCallback.Lifecycle Timing: Don’t modify parameters in
OnInitialized(useOnParametersSetinstead).
7. Key Takeaways
Parameters: Pass data from parent to child.
EventCallback: Notify parents of child events.
Lifecycle Methods: Control initialization and updates.
Cascading Values: Share values across nested components.