Skip to content

data-wp-input: Interactivity API two-way input binding directive - #80021

Open
nickchomey wants to merge 13 commits into
WordPress:trunkfrom
nickchomey:add/iapi-input-directive
Open

data-wp-input: Interactivity API two-way input binding directive#80021
nickchomey wants to merge 13 commits into
WordPress:trunkfrom
nickchomey:add/iapi-input-directive

Conversation

@nickchomey

@nickchomey nickchomey commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Closes: #80023

Note: this PR stacks on top of #79975, which refactors the directives mechanism to be cleaner and more extensible. Should probably review that first, though I can rebase this on trunk if needed.

Description

Inspired by datastar's bind attribute, this PR implements a new data-wp-input directive for the Interactivity API that provides two-way binding between input elements and signals. This collapses data-wp-bind--value + data-wp-on--input into a single attribute.

Features

  • Two-way binding: signal→element and element→signal
  • Auto-detects element type: checkbox, radio, range/number, file, select (single+multiple), text/textarea, custom elements
  • Supports both state and context paths
  • Element→signal seeding when signal is undefined
  • Multi-select live updates via layout effect
  • 17 e2e tests covering all element types with state + context variants

How it works

The directive navigates through the store/context proxy normally (no peek for writes), so each intermediate key returns a proxified object, and the final leaf assignment goes through the proxy's set/defineProperty traps, so it is fully reactive at any depth.

Use of AI Tools

AI assistance: Yes
Tool(s): VSCode Copilot Chat
Model(s): Deepseek V4 Flash, GLM 5.2
Used for: Pair programmer. I guided and reviewed it all

@github-actions github-actions Bot added the [Package] Interactivity /packages/interactivity label Jul 8, 2026
@nickchomey
nickchomey marked this pull request as ready for review July 8, 2026 20:16
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Interactivity.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

2 similar comments
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Interactivity.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Warning: Type of PR label mismatch

To merge this PR, it requires exactly 1 label indicating the type of PR. Other labels are optional and not being checked here.

  • Required label: Any label starting with [Type].
  • Labels found: [Package] Interactivity.

Read more about Type labels in Gutenberg. Don't worry if you don't have the required permissions to add labels; the PR reviewer should be able to help with the task.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: nickchomey <nickchomey@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@nickchomey nickchomey changed the title [WIP] data-wp-input: Two-way input binding directive data-wp-input: Interactivity API two-way input binding directive Jul 8, 2026
@nickchomey
nickchomey force-pushed the add/iapi-input-directive branch 5 times, most recently from bbfb7d1 to 433be41 Compare July 13, 2026 18:13
@nickchomey

Copy link
Copy Markdown
Contributor Author

@DAreRodz This would be a larger review, so not urgent, but would be great to get any feedback when you have a chance! I'll rebase it onto trunk once #79975 is merged, so that the diff will be vastly smaller.

@nickchomey
nickchomey force-pushed the add/iapi-input-directive branch 5 times, most recently from 674f3de to ce0a531 Compare July 16, 2026 15:24
@nickchomey

Copy link
Copy Markdown
Contributor Author

@DAreRodz this is been rebased on trunk now, to account for the refactoring.

There's one commit that fixes some other small linting issues that I found when fixing lint issues for the input directive - happy to remove it if you prefer.

@nickchomey
nickchomey force-pushed the add/iapi-input-directive branch from ce0a531 to ddf3394 Compare August 6, 2026 17:32
…up nesting

- Fix TypeScript build errors: narrow entry.value (string|object) to string via
  local  variable; restore required  arg on useLayoutEffect.
- Make layout effect depend on [signalValue] so it re-runs on every signal
  change, keeping <select multiple> in sync (Preact diff doesn't handle
  multi-select value arrays).
- Remove redundant useWatch for multi-select (layout effect now covers it).
- Change checkbox-group test from indexed array paths (state.tags.0/.1) to
  top-level properties (state.tags0/.1), because WP's state proxy does not
  make nested arrays reactive — writing to raw array indices bypasses the
  proxy set trap and never fires the signal.
- All 14 tests: 13 passed, 1 skipped (seed test — known timing issue).
Changes:
- Fix ESLint errors: replace nested ternaries with if/else, use !== instead of !=,
  add eslint-disable for exhaustive-deps warning
- Fix toggle text test: also check input element value after toggle
- Fix skipped test: rename properly, remove unused output const, unskip
- Add no-pre-selected radio and select test cases with render.php/view.js support
- All 16 tests pass, 0 failed, 0 skipped, ESLint clean
… expand tests

- Replace setByPath with local writeSignal/readSignal helpers that handle
  both state.* and context.* paths via normal proxy navigation (no peek)
- Remove all setByPath references (input.ts + store.ts)
- Add context-based binding tests merged into existing state tests for:
  text, checkbox, number, select, radio, range, textarea, multi-select
- Add context toggle actions: toggleCtxChecked, toggleCtxNum,
  toggleCtxPet, toggleCtxText, toggleCtxMultiPet
- All 16 tests pass, ESLint clean, build clean
- Add file input test (skipped — FileReader async timing issue to investigate)
- Fix all ESLint errors in input.ts (eqeqeq, unused vars, var-before-return)
- Move writeSignal/readSignal creation after PENDING_GETTER check
- All 17 tests: 16 passed, 1 skipped, ESLint clean
- writeSignal/readSignal were created AFTER the file input check, causing
  a temporal dead zone issue — the useInit callback captured uninitialized
  const variables and threw ReferenceError on access.
- Moved writeSignal/readSignal creation to before the file input check,
  with eslint-disable comments for no-unused-vars-before-return.
- Unskipped the file input test — all 17 tests now pass (17 passed, 0 failed, 0 skipped)
- Change from fileCount getter to fileName getter (returns first file's name)
- Add context file input with data-wp-text="context.ctxFileData.0.name"
  path navigation — proves the file name is stored and accessible
- Both state and context file inputs now pass with full file name assertion
- All 17 tests pass, ESLint clean
@nickchomey
nickchomey force-pushed the add/iapi-input-directive branch from ddf3394 to 90441ae Compare August 12, 2026 03:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Interactivity /packages/interactivity

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a data-wp-input directive to Interactivity API

1 participant