Skip to content
Closed
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
13 changes: 13 additions & 0 deletions .squad/agents/jubilee/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,16 @@ This wave establishes **documentation patterns** that will guide future control
- **Page uses `@inject ClientScriptShim ClientScript`** — injected as scoped service. Calls `FlushAsync(JS)` in `OnAfterRenderAsync` since the page doesn't inherit BaseWebFormsComponent.
- **Pattern:** Source code section at bottom showing complete `@code` block with escaped `@@` directives for display. Follows established migration demo conventions.
- **Build verified:** 0 errors, pre-existing BL0005 warnings only.

### PostBack & ScriptManager Demo Page (ClientScript Phase 2)

- **Created** `samples/AfterBlazorServerSide/Components/Pages/ControlSamples/PostBackDemo/Index.razor` — three-section demo page for Phase 2 ClientScript postback shims.
- **Section 1: GetPostBackEventReference** — button with `onclick="@_postBackScript"` fires `__doPostBack` from JS. PostBack event on WebFormsPageBase receives it server-side. Stable IDs: `postback-button`, `postback-script`, `postback-result`.
- **Section 2: GetPostBackClientHyperlink** — anchor `href="@_postBackHyperlink"` triggers postback via `javascript:__doPostBack(...)` URL. Stable IDs: `postback-link`, `hyperlink-script`, `hyperlink-result`.
- **Section 3: ScriptManager.GetCurrent** — uses `ScriptManagerShim.GetCurrent(this)` to register startup script that writes into `#scriptmanager-target`. Same Web Forms code pattern.
- **Source Code section** at bottom with escaped `@@` directives.
- **Inherits WebFormsPageBase** (not `@inject`) — gives access to `ClientScript`, `PostBack` event, and `ScriptManagerShim.GetCurrent(this)`. This differs from the ClientScriptShim demo which uses `@inject`.
- **Updated** `ComponentCatalog.cs` — added "PostBack Demo" entry in "Migration Helpers" category after "IsPostBack".
- **Updated** `ComponentList.razor` — added PostBack & ScriptManager link in Migration Helpers section.
- **Build verified:** 0 errors, pre-existing BL0005 warnings only.
- **Lesson:** Pages that need the PostBack event must `@inherits WebFormsPageBase`. The ClientScript property is available via inheritance (no separate `@inject` needed). `OnAfterRenderAsync` in WebFormsPageBase handles `FlushAsync` automatically.
Expand Down
14 changes: 12 additions & 2 deletions docs/Analyzers/BWFC022.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ If you prefer to modernize your code now, rewrite to `IJSRuntime` directly. The
| `RegisterStartupScript()` | `ClientScriptShim` (⭐ Easy) or `OnAfterRenderAsync()` + `IJSRuntime` (⭐⭐ Moderate) | ⭐ Easy |
| `RegisterClientScriptInclude()` | `ClientScriptShim` (⭐ Easy) or `<script>` tag in layout (⭐ Easy) | ⭐ Easy |
| `RegisterClientScriptBlock()` | `ClientScriptShim` (⭐ Easy) or JS module (⭐ Easy) | ⭐ Easy |
| `GetPostBackEventReference()` | `@onclick` or `EventCallback<T>` | ⭐⭐ Medium |
| `GetPostBackEventReference()` | `ClientScriptShim` (⭐ Easy — Phase 2) or `@onclick` / `EventCallback<T>` (⭐⭐ Medium) | ⭐ Easy |

### Common Fix: Startup Script

Expand Down Expand Up @@ -144,7 +144,17 @@ If you prefer to modernize your code now, rewrite to `IJSRuntime` directly. The
}
```

=== "Blazor (After)"
=== "Blazor (After — Phase 2 with Shim, Zero Rewrite)"
```csharp
// Same code works! ClientScriptShim returns __doPostBack() string
public string GetDeleteButtonScript()
{
return ClientScript.GetPostBackEventReference(
new PostBackOptions(btnDelete, "clicked"));
}
```

=== "Blazor (Modern Approach)"
```razor
<button @onclick="HandleDelete">Delete</button>

Expand Down
45 changes: 38 additions & 7 deletions docs/Analyzers/BWFC024.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@

This analyzer warns when you use `ScriptManager` code-behind methods like `GetCurrent()`, `SetFocus()`, `RegisterAsyncPostBackControl()`, and similar — Web Forms APIs for managing client scripts and UpdatePanel behavior.

**Note:** Phase 2 now includes support for `GetCurrent()` and script registration methods via `ScriptManagerShim`. Methods like `SetFocus()` and `RegisterAsyncPostBackControl()` still require modernization.

**Detected patterns:**
- `ScriptManager.GetCurrent(Page)` / `ScriptManager.GetCurrent(this)`
- `.SetFocus(control)`
- `.RegisterAsyncPostBackControl(control)`
- `.RegisterUpdateProgress(...)`
- `.RegisterPostBackControl(...)`
- `ScriptManager.GetCurrent(Page)` / `ScriptManager.GetCurrent(this)` — ✅ Phase 2 supported
- `.SetFocus(control)` — ❌ Still requires JS interop
- `.RegisterAsyncPostBackControl(control)` — ❌ Still requires component binding
- `.RegisterUpdateProgress(...)` — ❌ Still requires component state
- `.RegisterPostBackControl(...)` — ❌ Not supported

---

Expand Down Expand Up @@ -60,7 +62,36 @@ These methods have **no direct equivalents**. Each requires a different approach

## How to Fix

The fix depends on **which** ScriptManager method you're using.
The fix depends on **which** ScriptManager method you're using and which Phase you're in.

### ✅ Phase 2: GetCurrent() and Script Registration Methods

`ScriptManager.GetCurrent()` now returns a working `ScriptManagerShim` that delegates to `ClientScriptShim`.

=== "Web Forms (Before)"
```csharp
protected void Page_Load(object sender, EventArgs e)
{
ScriptManager sm = ScriptManager.GetCurrent(Page);
sm.RegisterStartupScript(this.GetType(), "init", "initPage();", true);
}
```

=== "Blazor (After — Phase 2, Zero Rewrite)"
```csharp
protected override void OnInitialized()
{
// Same code works! ScriptManagerShim returns the component's ClientScriptShim
ScriptManager sm = ScriptManager.GetCurrent(this);
sm.RegisterStartupScript(this.GetType(), "init", "initPage();", true);
}
```

---

### Still Requiring Modernization

Other ScriptManager methods still require refactoring. See the fixes below.

### Fix 1: SetFocus() → JavaScript Interop

Expand Down Expand Up @@ -245,7 +276,7 @@ await module.InvokeVoidAsync("focusElement", searchBox);

| Web Forms Method | Blazor Equivalent | Approach |
|---|---|---|
| `GetCurrent(Page)` | — | Remove; use component state |
| `GetCurrent(Page)` | `ScriptManager.GetCurrent(this)` (Phase 2 — Zero Rewrite) | Easy |
| `.SetFocus(control)` | `JS.InvokeVoidAsync("focus", @ref)` | JavaScript interop |
| `.RegisterAsyncPostBackControl()` | Component parameter binding | Remove; use `@bind` or `EventCallback` |
| `.RegisterPostBackControl()` | — | Remove; not needed in Blazor |
Expand Down
Loading
Loading