From 6605bf452fd48bd47bd1b375bb05d69ce6f61085 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 6 Mar 2026 20:13:55 +0000 Subject: [PATCH] Fix DataStar v1 RC8 signal attribute incompatibilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs that caused signals to not work on the frontend: 1. data-on-signal-change → data-on-signal-patch The data-on-signal-change attribute was removed in RC8. The replacement is data-on-signal-patch. 2. data-bind-newTodo="" → data-bind="newTodo" HTML normalises attribute names to lowercase at parse time, so data-bind-newTodo becomes data-bind-newtodo in the DOM. DataStar would then bind to signal $newtodo instead of $newTodo, breaking the two-way binding. The value syntax data-bind="newTodo" preserves the camelCase name correctly. https://claude.ai/code/session_01JThiQbp3Bn9J1VhBpRuz4u --- examples/todo/app.rs | 7 ++++--- examples/todo/todo_list.rs | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/todo/app.rs b/examples/todo/app.rs index 554fa0f..2aceeb9 100644 --- a/examples/todo/app.rs +++ b/examples/todo/app.rs @@ -42,7 +42,8 @@ pub fn router(state: SharedState) -> Router { /// /// DataStar v1 contract (verified against https://data-star.dev/reference): /// - `data-signals` — initialize signals (JS object literal syntax) -/// - `data-on-signal-change` — fires when any signal changes +/// - `data-on-signal-patch` — fires when any signal is patched (renamed from +/// `data-on-signal-change` which was removed in RC8) /// - `__debounce.300ms` — modifier: debounce 300ms /// - `@post('/render')` — send all non-_ signals as JSON body /// - `@get('/sse?conn=...')` — open long-lived SSE pipe @@ -70,7 +71,7 @@ fn document_shell(conn_id: Uuid, initial_signals: &str, inner_html: &str) -> Str
{inner}
@@ -210,7 +211,7 @@ async fn initial_about_load(State(state): State) -> impl IntoRespon /// `POST /render` — Signal-triggered rerender. /// /// DataStar sends all non-`_` signals as JSON body when any signal changes -/// (triggered by `data-on-signal-change` + `@post('/render')`). +/// (triggered by `data-on-signal-patch` + `@post('/render')`). /// /// Returns `Content-Type: text/event-stream` with a single /// `datastar-patch-elements` event containing the full page HTML. diff --git a/examples/todo/todo_list.rs b/examples/todo/todo_list.rs index 0f8ceb8..82f2342 100644 --- a/examples/todo/todo_list.rs +++ b/examples/todo/todo_list.rs @@ -40,13 +40,15 @@ pub async fn todo_list(cx: &mut RenderContext) -> anyhow::Result { } // Add todo form. - // data-bind-newTodo binds the input to the $newTodo signal. - // The button uses new_todo.val ("$newTodo") in a DataStar expression. + // data-bind="newTodo" binds the input to the $newTodo signal. + // Value syntax is used instead of data-bind-newTodo because HTML + // normalises attribute names to lowercase, which would corrupt the + // camelCase signal name (newTodo → newtodo). div.add-form { input type="text" placeholder="What needs to be done?" - data-bind-newTodo="" + data-bind="newTodo" ; button data-on-click="@post('/action/add_todo')"