From 320ac1bc5d59ca67da075af21273e2ed741139cb Mon Sep 17 00:00:00 2001 From: Erick Xavier Date: Tue, 7 Jul 2026 23:19:09 -0300 Subject: [PATCH 1/2] fix/NOJS-244-NOJS-260: sync directive incompatibility docs Add limitation notes for 6 documented directive incompatibilities: - conditionals.md: if+loop, case/default+loop edge cases - loops.md: new Directive Compatibility Notes section - binding.md: bind+t, bind-value+model, model+bind-value notes - state.md: watch+on:change on form controls - i18n.md: t+bind double text-writer - validation.md: new section 4 with all 6 LSP diagnostics - SKILL.md: new section 6.5 Directive Compatibility table --- nojs/SKILL.md | 14 +++ nojs/references/directives/binding.md | 4 + nojs/references/directives/conditionals.md | 6 ++ nojs/references/directives/i18n.md | 1 + nojs/references/directives/loops.md | 12 +++ nojs/references/directives/state.md | 1 + nojs/references/validation.md | 111 +++++++++++++++++++-- 7 files changed, 143 insertions(+), 6 deletions(-) diff --git a/nojs/SKILL.md b/nojs/SKILL.md index 11aa98d..d721059 100644 --- a/nojs/SKILL.md +++ b/nojs/SKILL.md @@ -469,6 +469,20 @@ Browser globals (`window`, `document`, `location`, `history`, `navigator`) avail - Statement write-back: in `on:*`/`watch`, mutated variables auto-write-back to the owning context - AST caching: LRU-cached (configurable: `exprCacheSize`, default 500) + +## 6.5. Directive Compatibility + +Certain directive combinations on the same element produce unexpected behavior. The NoJS LSP warns about these during development. + +| Combination | Problem | Fix | +|------------|---------|-----| +| `case`/`default` + `each`/`foreach`/`for` | Switch becomes inert; all branches render | Move loop inside the case branch | +| `if` + `each`/`foreach`/`for` | Condition cannot filter individual items | Use `filter` attribute or wrap in container with `if` | +| `ref` + `each`/`foreach`/`for` | Every clone re-registers; `$refs` points to last clone | Remove `ref` or access via loop context | +| `bind-value` + `model` | Redundant two-way bindings; duplicate listeners | Use one: `model` (preferred) or `bind-value` | +| `watch` + `on:change` (on form controls) | Both claim the change event; may conflict | Use `watch` with its `on:change` companion OR a standalone `on:change` | +| `t` + `bind` | Both write text content; last-processed wins silently | Use one text source per element | + ## 7. Config Reference | Option | Default | Description | diff --git a/nojs/references/directives/binding.md b/nojs/references/directives/binding.md index 131eeed..d6a9cad 100644 --- a/nojs/references/directives/binding.md +++ b/nojs/references/directives/binding.md @@ -44,6 +44,7 @@ Replaces the element's text content with the evaluated expression. Supports pipe - When the expression evaluates to `null` or `undefined`, the text content is set to an empty string. - Pipe expressions are evaluated left to right: `bind="value | filterA | filterB"` passes the result of `filterA` into `filterB`. - HTML entities in the expression result are rendered as literal text (not HTML). Use `bind-html` for HTML output. +- **Incompatible with `t` on the same element:** Both `bind` and `t` write text content. The last-processed directive wins silently. Use only one text source per element. ### Complete Example @@ -105,6 +106,8 @@ Works with any attribute: `src`, `href`, `alt`, `title`, `disabled`, `checked`, On ``, `