Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# BladeContext Rename

## Summary

`IBladeService` has been renamed to `IBladeContext` and `BladeService` has been renamed to `BladeContext` to clarify that this is a context service accessed via `UseContext<T>()`, not a DI service.

## What Changed

### Before
```csharp
var blades = UseContext<IBladeService>();
```

### After
```csharp
var blades = UseContext<IBladeContext>();
```

## How to Find Affected Code

Run `dotnet build`.

Or search for:
- `IBladeService`
- `BladeService`
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ All Ivy types are in the root `Ivy` namespace. There are no sub-namespaces. You
using Ivy;
```

This single using statement gives you access to everything: `ViewBase`, `IState<T>`, `MetricView`, `MetricRecord`, chart views (`LineChartView`, `PieChartView`, `BarChartView`, `AreaChartView`), `DataTable`, `DataTableBuilder<T>`, layout helpers (`Layout.Vertical()`, `Layout.Horizontal()`), `Button`, `TextInput`, all input types, `Card`, `Dialog`, `Sheet`, `Tab`, `Icons`, `RefreshToken`, `IClientProvider`, `IBladeService`, `IConnection`, `IHaveSecrets`, and all other framework types.
This single using statement gives you access to everything: `ViewBase`, `IState<T>`, `MetricView`, `MetricRecord`, chart views (`LineChartView`, `PieChartView`, `BarChartView`, `AreaChartView`), `DataTable`, `DataTableBuilder<T>`, layout helpers (`Layout.Vertical()`, `Layout.Horizontal()`), `Button`, `TextInput`, all input types, `Card`, `Dialog`, `Sheet`, `Tab`, `Icons`, `RefreshToken`, `IClientProvider`, `IBladeContext`, `IConnection`, `IHaveSecrets`, and all other framework types.

**Do NOT use sub-namespaces** like `Ivy.Components`, `Ivy.Views.Dashboards`, `Ivy.Widgets.DataTables`, `Ivy.Client`, `Ivy.Hooks`, `Ivy.Services`, or `Ivy.Apps`. These do not exist — the framework source code organizes files in subdirectories but all types use `namespace Ivy;`.

Expand Down
24 changes: 12 additions & 12 deletions src/Ivy.Docs.Shared/Docs/02_Widgets/03_Common/12_Blades.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ searchHints:
Create stacked [navigation](../../01_Onboarding/02_Concepts/09_Navigation.md) experiences where new [views](../../01_Onboarding/02_Concepts/02_Views.md) slide in from the right, managed through a blade controller for intuitive drill-down interfaces.
</Ingress>

`Blade`s provide a stacked navigation pattern where new views slide in from the right. Use the `UseBlades` extension to create a root blade and manage a stack of blades through `IBladeService`. Perfect for master-detail [interfaces](../../01_Onboarding/02_Concepts/02_Views.md), wizards, and hierarchical navigation.
`Blade`s provide a stacked navigation pattern where new views slide in from the right. Use the `UseBlades` extension to create a root blade and manage a stack of blades through `IBladeContext`. Perfect for master-detail [interfaces](../../01_Onboarding/02_Concepts/02_Views.md), wizards, and hierarchical navigation.

## Usage

Create a blade container with a root view and use `IBladeService` to push and pop blades. Use [Size](../../04_ApiReference/Ivy/Size.md) for blade `width` (e.g. `Size.Units(100)`).
Create a blade container with a root view and use `IBladeContext` to push and pop blades. Use [Size](../../04_ApiReference/Ivy/Size.md) for blade `width` (e.g. `Size.Units(100)`).

```csharp demo-tabs
public class BladeNavigationDemo : ViewBase
Expand All @@ -38,7 +38,7 @@ public class NavigationRootView : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var index = blades.GetIndex(this);

return Layout.Horizontal().Height(Size.Units(50))
Expand Down Expand Up @@ -70,7 +70,7 @@ public class SearchableListView : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var searchTerm = UseState("");
var products = new[] { "iPhone 15", "MacBook Pro", "iPad Air", "Apple Watch", "AirPods Pro" };

Expand Down Expand Up @@ -131,7 +131,7 @@ public class RefreshRootView : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var items = UseState(new List<string> { "Item 1", "Item 2" });
var refreshToken = UseRefreshToken();

Expand Down Expand Up @@ -159,7 +159,7 @@ public class AddItemView(RefreshToken token) : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var name = UseState("New Item");

return Layout.Vertical().Gap(2)
Expand Down Expand Up @@ -191,7 +191,7 @@ public class ErrorRootView : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();

return Layout.Vertical()
| Text.Block("Click to push a blade that throws an exception")
Expand All @@ -212,18 +212,18 @@ public class BladeWithError : ViewBase

## UseBlades

The `UseBlades` hook creates a blade service context and initializes a root blade. It returns a `BladesView` that manages the blade stack and provides navigation through the `IBladeService` context.
The `UseBlades` hook creates a blade context context and initializes a root blade. It returns a `BladesView` that manages the blade stack and provides navigation through the `IBladeContext` context.

```mermaid
graph LR
A[UseBlades Hook] --> B[Create Blade Service]
A[UseBlades Hook] --> B[Create Blade Context]
B --> C[Initialize Root Blade]
C --> D[Create Context]
D --> E[Return BladesView]
```

<Callout Type="info">
In most cases, you'll use `UseBlades()` directly in your views. The hook manages the blade stack and provides `IBladeService` through context for pushing and popping blades.
In most cases, you'll use `UseBlades()` directly in your views. The hook manages the blade stack and provides `IBladeContext` through context for pushing and popping blades.
</Callout>


Expand Down Expand Up @@ -268,6 +268,6 @@ Key rules:
- Use `Text.Literal()` for blade titles, not `Text.H3()`
- Place action buttons inside the `Layout.Horizontal()` with `.Ghost()` styling

### Why does UseService<IBladeService>() return null?
### Why does UseService<IBladeContext>() return null?

`IBladeService` is not registered in the DI container. It is a context service provided by `UseBlades()`. Use `UseContext<IBladeService>()` instead. `UseService<T>()` is only for application-registered DI services like database factories or HTTP clients.
`IBladeContext` is not registered in the DI container. It is a context service provided by `UseBlades()`. Use `UseContext<IBladeContext>()` instead. `UseService<T>()` is only for application-registered DI services like database factories or HTTP clients.
2 changes: 1 addition & 1 deletion src/Ivy.Docs.Shared/Docs/03_Hooks/01_HookIntroduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ public class NavigationRootView : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var index = blades.GetIndex(this);

return Layout.Horizontal().Height(Size.Units(50))
Expand Down
8 changes: 4 additions & 4 deletions src/Ivy.Docs.Shared/Docs/05_Other/Hallucinations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2945,21 +2945,21 @@ b73d8115-b4d2-45d5-926e-0a915c1dca63

## UseService vs UseContext — blade/context services

LLMs sometimes use `UseService<IBladeService>()` to obtain the blade service. This is incorrect — `IBladeService` is a **context** service provided by `UseBlades()`, not a DI-registered service. Using `UseService` returns `null`, causing `NullReferenceException` at runtime.
LLMs sometimes use `UseService<IBladeContext>()` to obtain the blade context. This is incorrect — `IBladeContext` is a **context** provided by `UseBlades()`, not a DI-registered service. Using `UseService` returns `null`, causing `NullReferenceException` at runtime.

**Wrong:**

```csharp
var bladeService = UseService<IBladeService>(); // Returns null!
var blades = UseService<IBladeContext>(); // Returns null!
```

**Correct:**

```csharp
var bladeService = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
```

**Rule:** Use `UseContext<T>()` for framework-provided context services (`IBladeService`, etc.). Use `UseService<T>()` only for application-registered DI services (e.g., `DbContextFactory`, `HttpClient`).
**Rule:** Use `UseContext<T>()` for framework-provided context services (`IBladeContext`, etc.). Use `UseService<T>()` only for application-registered DI services (e.g., `DbContextFactory`, `HttpClient`).

**Found In:**
0e9fc5ed-1724-4fed-b9ea-44b370358457 (4 instances across CategoryListBlade, CategoryDetailsBlade, TagListBlade, TagDetailsBlade)
Expand Down
2 changes: 1 addition & 1 deletion src/Ivy.Samples.Shared/Apps/Concepts/BladesApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class RootView(string someId) : ViewBase
{
public override object? Build()
{
var bladeController = UseContext<IBladeService>();
var bladeController = UseContext<IBladeContext>();
var index = bladeController.GetIndex(this);

void OnClick(Event<Button> @event)
Expand Down
4 changes: 2 additions & 2 deletions src/Ivy.Samples.Shared/Apps/Demos/Database/CategoriesApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class CategoriesListBlade : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var refreshToken = UseRefreshToken();

var filter = UseState("");
Expand Down Expand Up @@ -136,7 +136,7 @@ public class CategoryDetailsBlade(Guid categoryId) : ViewBase
public override object? Build()
{
var factory = UseService<SampleDbContextFactory>();
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var queryService = UseService<IQueryService>();

var categoryQuery = UseQuery(
Expand Down
4 changes: 2 additions & 2 deletions src/Ivy.Samples.Shared/Apps/Demos/Database/DepartmentsApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class DepartmentsListBlade : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var refreshToken = UseRefreshToken();

var filter = UseState("");
Expand Down Expand Up @@ -136,7 +136,7 @@ public class DepartmentDetailsBlade(Guid departmentId) : ViewBase
public override object? Build()
{
var factory = UseService<SampleDbContextFactory>();
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var queryService = UseService<IQueryService>();

var departmentQuery = UseQuery(
Expand Down
4 changes: 2 additions & 2 deletions src/Ivy.Samples.Shared/Apps/Demos/Database/ProductsApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class ProductsListBlade : ViewBase
{
public override object? Build()
{
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var refreshToken = UseRefreshToken();

// Filter state with throttling for search
Expand Down Expand Up @@ -138,7 +138,7 @@ public class ProductDetailsBlade(Guid productId) : ViewBase
public override object? Build()
{
var factory = UseService<SampleDbContextFactory>();
var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();
var queryService = UseService<IQueryService>();

var productQuery = UseQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class BladeContent : ViewBase
{
public override object? Build()
{
var bladeController = UseContext<IBladeService>();
var bladeController = UseContext<IBladeContext>();

void PushNoWidth(Event<Button> e) => bladeController.Push(this, new BladeTableNoWidth(), "No Width");
void PushFull(Event<Button> e) => bladeController.Push(this, new BladeTableFull(), "Width: Full");
Expand Down
2 changes: 1 addition & 1 deletion src/Ivy.Samples.Shared/Apps/Widgets/ListApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class ListBlade : ViewBase
var searchString = UseState("");
var filteredProducts = UseState(products);

var blades = UseContext<IBladeService>();
var blades = UseContext<IBladeContext>();

UseEffect(() =>
{
Expand Down
2 changes: 1 addition & 1 deletion src/Ivy/Views/Blades/BladesView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class BladesView : ViewBase
{
public override object? Build()
{
var controller = UseContext<IBladeService>();
var controller = UseContext<IBladeContext>();

var blades = controller.Blades.Value
.Select(e => new BladeView(
Expand Down
10 changes: 5 additions & 5 deletions src/Ivy/Views/Blades/UseBlades.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// ReSharper disable once CheckNamespace
namespace Ivy;

public interface IBladeService
public interface IBladeContext
{
IState<ImmutableArray<BladeItem>> Blades { get; }

Expand All @@ -20,14 +20,14 @@ public interface IBladeService
int GetIndex(IView bladeView);
}

public class BladeService : IBladeService
public class BladeContext : IBladeContext
{
public BladeService()
public BladeContext()
{
Blades = new State<ImmutableArray<BladeItem>>([]);
}

public BladeService(IState<ImmutableArray<BladeItem>> blades)
public BladeContext(IState<ImmutableArray<BladeItem>> blades)
{
Blades = blades;
}
Expand Down Expand Up @@ -88,7 +88,7 @@ public static class UseBladesExtensions
public static IView UseBlades(this IViewContext context, Func<IView> rootBlade, string? title = null, Size? width = null)
{
var blades = context.UseState<ImmutableArray<BladeItem>>(() => [new BladeItem(rootBlade(), 0, title, width)]);
context.CreateContext<IBladeService>(() => new BladeService(blades));
context.CreateContext<IBladeContext>(() => new BladeContext(blades));
IView bladeView = new BladesView();
return bladeView;
}
Expand Down
Loading