Embedded Languages
Waltzing supports embedded JavaScript, CSS, and JSON blocks with full template interpolation.
Matching Backticks Rule
The number of backticks in the opening tag must match the closing tag: @``` closes with ```@, and @```` closes with ````@.
JSON
Embed JSON data with template interpolation:
Basic Object
<div x-data=@```json {
open: false,
count: @initial_count,
items: @items_json,
userId: @user.id
} ```@>
<button @click="open = !open">Toggle</button>
<div x-show="open">Content here</div>
</div> With Methods
<div x-data=@```json {
isOpen: false,
count: 0,
toggle() {
this.isOpen = !this.isOpen;
},
increment() {
this.count++;
},
async fetchData() {
const response = await fetch('/api/data');
this.data = await response.json();
}
} ```@>
<button @click="toggle()">Toggle</button>
<button @click="increment()">Count: <span x-text="count"></span></button>
</div> With Getters and Setters
<div x-data=@```json {
firstName: "@user.first_name",
lastName: "@user.last_name",
get fullName() {
return this.firstName + ' ' + this.lastName;
},
set fullName(value) {
const parts = value.split(' ');
this.firstName = parts[0] || '';
this.lastName = parts[1] || '';
}
} ```@>
<input x-model="fullName" />
<p x-text="fullName"></p>
</div> With Control Flow
<div x-data=@```json {
userId: @user.id,
@if user.is_admin {
isAdmin: true,
permissions: @admin_permissions,
}
@for field in default_fields {
@field.name: @field.default_value,
}
} ```@>
...
</div> JSON Arrays
<script>
const items = @```json [
@for item in items {
{ "id": @item.id, "name": "@item.name", "active": @item.active }
}
] ```@;
</script> JavaScript
Embed JavaScript with template values:
Configuration Objects
<script>
@```js
const config = {
apiUrl: "@api_url",
userId: @user.id,
debug: @is_debug,
features: @features_json
};
initApp(config);
```@
</script> With Control Flow
<script>
@```js
const handlers = {
@for handler in event_handlers {
"@handler.event": @handler.callback,
}
};
@if include_analytics {
initAnalytics("@tracking_id");
}
@for script in inline_scripts {
@script
}
```@
</script> Event Handler Registration
<script>
@```js
document.addEventListener('DOMContentLoaded', () => {
@for element in interactive_elements {
document.getElementById("@element.id")
.addEventListener("@element.event", (e) => {
@element.handler
});
}
});
```@
</script> CSS
Dynamic CSS with template interpolation:
Theme Variables
<style>
@```css
:root {
--primary-color: @theme.primary;
--secondary-color: @theme.secondary;
--font-family: "@theme.font_family";
--border-radius: @(theme.border_radius)px;
}
.theme-@theme.name {
background-color: @theme.background;
color: @theme.foreground;
}
```@
</style> With Control Flow
<style>
@```css
@for breakpoint in breakpoints {
@@media (min-width: @(breakpoint.width)px) {
.container {
max-width: @(breakpoint.max_width)px;
}
}
}
@if dark_mode_enabled {
@@media (prefers-color-scheme: dark) {
:root {
--bg-color: #1a1a1a;
--text-color: #ffffff;
}
}
}
@for color in brand_colors {
.text-@color.name {
color: @color.value;
}
.bg-@color.name {
background-color: @color.value;
}
}
```@
</style> Inline Styles
<div style="@```style
color: @text_color;
background: @bg_color;
padding: @(padding)px;
@if has_border {
border: 1px solid @border_color;
}
```@">
Content
</div> Important Notes
Escaping @ in Embedded Blocks
Inside embedded blocks, use @@ to output a literal @ character:
@* In CSS - @@media becomes @media *@
@```css
@@media (min-width: 768px) { ... }
```@
@* @@click becomes @click in attributes *@
<button @click="toggle()">Toggle</button> String vs Number Values
Use quotes for string values, no quotes for numbers/booleans:
@```json {
name: "@user.name", @* String - quoted *@
count: @item_count, @* Number - unquoted *@
active: @is_active, @* Boolean - unquoted *@
items: @items_json @* Pre-serialized JSON - unquoted *@
} ```@ Commas After Control Flow
Commas after @if, @for, and @match blocks are optional in JSON:
@```json {
baseField: true
@if extra {
extraField: @extra_value
}
@for item in items {
@item.key: @item.value
}
finalField: false
} ```@