WakaPAC uses the data-pac-bind attribute to connect your data to DOM elements. Bindings automatically synchronize between your data and the page - when data changes, the DOM updates, and when users interact with form elements, your data updates.
The data-pac-bind attribute contains comma-separated binding declarations:
<element data-pac-bind="bindingType: expression, anotherType: expression">
Each binding has two parts:
includes(), indexOf(), join()One-way bindings flow data from your abstraction to the DOM. When your data changes, the DOM updates automatically:
visible, if, enable - Control element stateclass, style - Control appearancesrc, href, title, etc.)Two-way bindings flow data in both directions. DOM changes update your data, and data changes update the DOM:
value - For text inputs, textareas, select dropdownschecked - For checkboxesBindings re-evaluate automatically whenever the data they reference changes. For example, if a binding uses {{ user.name }}, it updates when user.name is assigned a new value. WakaPAC tracks dependencies and only updates affected bindings.
Two-way binding for text fields. Changes in the input update the data property, and changing the data property updates the input:
<div id="app">
<input data-pac-bind="value: username" type="text">
<textarea data-pac-bind="value: description"></textarea>
<p>Username: {{username}}</p>
<p>Description: {{description}}</p>
</div>
<script>
wakaPAC('#app', {
username: 'alice',
description: 'Software developer'
});
</script>
Track the selected option's value:
<div id="app">
<select data-pac-bind="value: selectedOption">
<option value="A">Option A</option>
<option value="B">Option B</option>
<option value="C">Option C</option>
</select>
<p>You selected: {{selectedOption}}</p>
</div>
<script>
wakaPAC('#app', {
selectedOption: 'B' // Pre-selects "Option B"
});
</script>
Two-way binding for checkbox state (true when checked, false when unchecked):
<div id="app">
<label>
<input type="checkbox" data-pac-bind="checked: isActive">
Active
</label>
<label>
<input type="checkbox" data-pac-bind="checked: newsletter">
Subscribe to newsletter
</label>
<p>Active: {{isActive}}, Newsletter: {{newsletter}}</p>
</div>
<script>
wakaPAC('#app', {
isActive: true,
newsletter: false
});
</script>
Radio buttons use value binding (not checked) because all radio buttons in a group bind to the same property. The bound property stores which radio button's value is currently selected:
<div id="app">
<label>
<input type="radio" name="theme" value="light" data-pac-bind="value: selectedTheme">
Light
</label>
<label>
<input type="radio" name="theme" value="dark" data-pac-bind="value: selectedTheme">
Dark
</label>
<label>
<input type="radio" name="theme" value="auto" data-pac-bind="value: selectedTheme">
Auto
</label>
<p>Selected theme: {{selectedTheme}}</p>
</div>
<script>
wakaPAC('#app', {
selectedTheme: 'light'
});
</script>
Controls element visibility using CSS display property. The element remains in the DOM but is hidden when the expression evaluates to false:
<div id="app">
<button data-pac-bind="click: toggle">Toggle</button>
<div data-pac-bind="visible: isVisible">
<p>This content is visible when isVisible is true</p>
</div>
<div data-pac-bind="visible: !isVisible">
<p>This shows when isVisible is false</p>
</div>
</div>
<script>
wakaPAC('#app', {
isVisible: true,
toggle() {
this.isVisible = !this.isVisible;
}
});
</script>
Clears and restores the element's innerHTML based on the condition. The outer element remains in the DOM but becomes empty when the condition is false:
<div id="app">
<div data-pac-bind="if: !isLoading">
<p>Content loaded successfully</p>
</div>
</div>
<script>
wakaPAC('#app', {
isLoading: false,
});
</script>
Use HTML comments to conditionally render content without wrapper elements. This is ideal for tables, grids, or when you need to control multiple sibling elements together:
<div id="app">
<!-- wp-if: !isLoading -->
<p>Content loaded successfully</p>
<!-- /wp-if -->
</div>
<script>
wakaPAC('#app', {
isLoading: false,
});
</script>
visible for frequently toggled content, preserving form state, or when you need CSS transitionsif when you already have a wrapper element and want to remove content from memory<!-- wp-if --> for table rows, grid items, multiple siblings, or when wrapper elements would break your layoutControls the disabled attribute on form elements. When the expression is true, the element is enabled; when false, it's disabled:
<div id="app">
<input data-pac-bind="value: email" placeholder="Enter email">
<button data-pac-bind="enable: isFormValid, click: submit">Submit</button>
<p data-pac-bind="visible: !isFormValid">Please enter a valid email address</p>
</div>
<script>
wakaPAC('#app', {
email: '',
computed: {
isFormValid() {
return this.email.includes('@') && this.email.length > 5;
}
},
submit() {
console.log('Form submitted:', this.email);
}
});
</script>
Apply CSS classes dynamically based on data. When using a string expression, the result becomes the element's class:
<div id="app">
<div data-pac-bind="class: currentTheme">
<p>This div has dynamic classes</p>
</div>
<button data-pac-bind="click: changeTheme">Change Theme</button>
</div>
<script>
wakaPAC('#app', {
currentTheme: 'dark',
changeTheme() {
this.currentTheme = this.currentTheme === 'dark' ? 'light' : 'dark';
}
});
</script>
Toggle multiple classes independently using an object. Each key is a class name, each value is a boolean expression:
<div id="app">
<div data-pac-bind="class: {active: isActive, error: hasError, 'user-premium': isPremium}">
<p>This div has conditional classes</p>
</div>
<button data-pac-bind="click: toggleActive">Toggle Active</button>
<button data-pac-bind="click: toggleError">Toggle Error</button>
</div>
<script>
wakaPAC('#app', {
isActive: true,
hasError: false,
isPremium: true,
toggleActive() {
this.isActive = !this.isActive;
},
toggleError() {
this.hasError = !this.hasError;
}
});
</script>
Apply inline CSS styles dynamically. Each key is a CSS property, each value is a string or expression:
<div id="app">
<div data-pac-bind="style: {color: textColor, fontSize: fontSize + 'px', backgroundColor: bgColor}">
<p>This text has dynamic styling</p>
</div>
<button data-pac-bind="click: increaseFontSize">Increase Font</button>
</div>
<script>
wakaPAC('#app', {
textColor: '#333',
fontSize: 16,
bgColor: '#f0f0f0',
increaseFontSize() {
this.fontSize += 2;
}
});
</script>
Bind any standard HTML attribute by using the attribute name as the binding type:
<div id="app">
<img data-pac-bind="src: imageUrl, alt: imageDescription">
<a data-pac-bind="href: linkUrl, title: linkTitle">Click here</a>
<input data-pac-bind="placeholder: placeholderText, maxlength: maxChars">
</div>
<script>
wakaPAC('#app', {
imageUrl: 'photo.jpg',
imageDescription: 'A beautiful photo',
linkUrl: 'https://example.com',
linkTitle: 'Visit our website',
placeholderText: 'Enter your name',
maxChars: 50
});
</script>
The foreach binding repeats an element for each item in an array, automatically updating when the array changes:
<div id="app">
<ul data-pac-bind="foreach: items">
<li>{{item}}</li>
</ul>
</div>
<script>
wakaPAC('#app', {
items: ['Apple', 'Banana', 'Cherry']
});
</script>
Use data-pac-item to give your iteration variable a meaningful name:
<div id="app">
<div data-pac-bind="foreach: users" data-pac-item="user">
<p>{{user.name}} - {{user.email}}</p>
</div>
</div>
<script>
wakaPAC('#app', {
users: [
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' }
]
});
</script>
WakaPAC provides the $index variable (0-based) inside foreach loops. The $ prefix prevents naming conflicts with your data properties:
<div id="app">
<div data-pac-bind="foreach: tasks" data-pac-item="task">
<p>{{$index + 1}}. {{task.title}}</p>
<button data-pac-bind="click: removeTask">Remove</button>
</div>
</div>
<script>
wakaPAC('#app', {
tasks: [
{ title: 'Learn WakaPAC' },
{ title: 'Build an app' },
{ title: 'Deploy to production' }
],
removeTask(task, index) {
// Click handlers receive (item, index, event) in foreach context
this.tasks.splice(index, 1);
}
});
</script>
You can customize the index variable name using data-pac-index:
<div data-pac-bind="foreach: items" data-pac-index="i">
<span>Item {{i}}: {{item}}</span>
</div>
Click handlers inside foreach loops automatically receive the current item and index as parameters:
methodName(item, index, event) {
// item: the current array element
// index: the array position (0-based)
// event: the original DOM event
}
You can nest foreach loops for multi-dimensional data. Each loop has its own item and index context:
<div id="app">
<div data-pac-bind="foreach: categories" data-pac-item="category">
<h3>{{category.name}}</h3>
<ul data-pac-bind="foreach: category.products" data-pac-item="product">
<li>{{product.name}} - ${{product.price}}</li>
</ul>
</div>
</div>
<script>
wakaPAC('#app', {
categories: [
{
name: 'Electronics',
products: [
{ name: 'Laptop', price: 999 },
{ name: 'Mouse', price: 25 }
]
},
{
name: 'Books',
products: [
{ name: 'JavaScript Guide', price: 39 },
{ name: 'Design Patterns', price: 45 }
]
}
]
});
</script>