fix(inertia-sails): ensure locals are accessible via locals.xxx in EJS templates#189
Merged
Merged
Conversation
…S templates
Sails's default EJS renderer creates an `options.locals` object for internal
helpers (blocks, layout, partial). EJS wraps templates in `with(data) { ... }`,
which causes `locals` inside the template to resolve to `data.locals` (the
Sails-created object) rather than the function parameter containing the actual
view data. This made `<%= locals.title %>` always return undefined.
Fix by pre-populating `data.locals` with user-provided locals so they survive
the `with` scoping.
Closes #188
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<%= locals.title %>in EJS templates always returnedundefined, causing fallback defaults to render instead of dynamic values passed via the locals APIThe Bug
When an action returns dynamic locals:
And the EJS template uses the documented
locals.xxxpattern:The rendered HTML always showed the fallback value (
My App) — the dynamic value was silently ignored.Root Cause
Sails's default EJS renderer (
default-view-rendering-fn.js) creates anoptions.locals = {}object to hold internal helpers (blocks,layout,partial). EJS compiles templates into a function wrapped withwith(data) { ... }. Inside thiswithblock:titleresolves todata.title→ the dynamic value ✓localsresolves todata.locals→ the Sails-created object (only hasblocks,layout,partial) ✗locals.title→data.locals.title→undefined→ falls back to default ✗The
withstatement causeslocalsto resolve to thedata.localsproperty (the nested Sails object) rather than thelocalsfunction parameter (which contains all the actual view data).The Fix
Pre-populate
data.localswith user-provided locals by passing them as a nestedlocalskey alongside the spread top-level properties:This ensures
data.localsalready contains the user's values when Sails's renderer checksif (!options.locals)— it finds our pre-populated object instead of creating an empty one. The renderer then adds its internal helpers (blocks,layout,partial) to the same object, so both user values and Sails internals coexist.Test plan
<%= locals.title %>renders dynamic values from action-level locals<%= locals.description %>renders dynamic values fromsails.inertia.local()<%= locals.ogImage %>renders dynamic values fromsails.inertia.localGlobally()<%= locals.title || 'Default' %>)<%- shipwright.styles() %>and<%- shipwright.scripts() %>still workpartial()andlayout()helpers still workCloses #188