Onchange
The onchange
event triggers whenever a reactive property of the component object this
changes. Reactive properties are those bound to the template and directly affect the UI. Note that state variables
have their dedicated callback and do not invoke the onchange event.
Examples
Reactive Properties
Reactive properties are those defined on this
object and referenced in the template. Changes to these properties automatically invoke the onchange
event.
Triggering Onchange
In the example below, the name property is reactive because it is referenced in the template.
<script src="https://lemonadejs.com/v5/lemonade.js"></script>
<div id='root'></div>
<script>
function Component() {
// Track any changes on properties used in the template
this.onchange = (prop) => {
console.log('The new value of', prop, ' is: ', this[prop]);
}
// Default name
this.name = 'Paul';
// Update name
const update = () => {
this.name = 'Jorge';
}
// Call the ready method when the DOM element is ready and appended to the DOM
return render => render`<div>
<p>Hello ${this.name}</p>
<input type="button" value="Update" onclick=${update} />
</div>`;
}
lemonade.render(Component, document.getElementById('root'));
</script>
</html>
export default function Component() {
// Track any changes on properties used in the template
this.onchange = (prop) => {
console.log('The new value of', prop, ' is: ', this[prop]);
}
// Default name
this.name = 'Paul';
// Update name
const update = () => {
this.name = 'Jorge';
}
// Call the ready method when the DOM element is ready and appended to the DOM
return render => render`<div>
<p>Hello ${this.name}</p>
<input type="button" value="Update" onclick=${update} />
</div>`;
}
Not Triggering Onchange
If a property is not used in the template, its changes will not invoke the onchange event.
<script src="https://lemonadejs.com/v5/lemonade.js"></script>
<div id='root'></div>
<script>
function Component() {
// Track any changes on properties used in the template
this.onchange = (prop) => {
console.log('The new value of', prop, ' is: ', this[prop]);
}
// Default name
this.name = 'Paul';
// Update name
const update = () => {
this.name = 'Jorge';
}
// Call the ready method when the DOM element is ready and appended to the DOM
return render => render`<div>
<p>Hello World</p>
<input type="button" value="Update" onclick=${update} />
</div>`;
}
lemonade.render(Component, document.getElementById('root'));
</script>
</html>
export default function Component() {
// Track any changes on properties used in the template
this.onchange = (prop) => {
console.log('The new value of', prop, ' is: ', this[prop]);
}
// Default name
this.name = 'Paul';
// Update name
const update = () => {
this.name = 'Jorge';
}
// Call the ready method when the DOM element is ready and appended to the DOM
return render => render`<div>
<p>Hello World</p>
<input type="button" value="Update" onclick=${update} />
</div>`;
}
Forcing Property Tracking
To monitor changes for properties not bound to the template, the track hook can be used to explicitly enable tracking. This ensures onchange is triggered even for properties that don’t directly affect the DOM.
<html>
<script src="https://lemonadejs.com/v5/lemonade.js"></script>
<div id='root'></div>
<script>
const { onchange, track } = lemonade;
function Test() {
// Default value
this.status = true;
// Status is not used in the template, but force tracking
track('status');
// Monitor changes on properties
onchange((prop, newValue, oldValue) => {
console.log(`${prop} has changed`, newValue, oldValue)
});
// Update a property
const update = () => {
this.status = !this.status;
}
return render => render`<div>
<input type="button" value="Update" onclick="${update}"/>
</div>`
}
lemonade.render(Test, document.getElementById('root'));
</script>
</html>
import { onchange, track } from 'lemonadejs';
function Component() {
// Default value
this.status = true;
// Status is not used in the template, but force tracking
track('status');
// Monitor changes on properties
onchange((prop, newValue, oldValue) => {
console.log(`${prop} has changed`, newValue, oldValue)
});
// Update a property
const update = () => {
this.status = !this.status;
}
return render => render`<div>
<input type="button" value="Update" onclick="${update}"/>
</div>`
}
Scope
The onchange event
can be defined as bound directly to the component or registered as a hook.
Bind to the Component Self
Define onchange directly on the component instance this
, making it accessible throughout the component.
<script src="https://lemonadejs.com/v5/lemonade.js"></script>
<div id='root'></div>
<script>
function Component() {
this.onchange = function() {
// Triggered when any property used in the template changes
}
return render => render`<div>
<b>Hello ${this.name}</b>
</div>`;
}
lemonade.render(Component, document.getElementById('root'));
</script>
</html>
function Test() {
this.onchange = function() {
// Triggered when any property used in the template changes
}
return render => render`<div>
<b>Hello ${this.name}</b>
</div>`;
}
Register The Event Privately
Registering onchange privately encapsulates its logic within the component, ensuring it is not accessible externally.
<script src="https://lemonadejs.com/v5/lemonade.js"></script>
<div id='root'></div>
<script>
let { onchange } = lemonade;
function Component() {
onchange(() => {
// Triggered when any property used in the template changes
})
return render => render`<div>
<b>Hello ${this.name}</b>
</div>`;
}
lemonade.render(Component, document.getElementById('root'));
</script>
</html>
import { onchange } from 'lemonadejs';
function Component() {
onchange(() => {
// Triggered when any property used in the template changes
})
return render => render`<div>
<b>Hello ${this.name}</b>
</div>`;
}
What's Next?
Another key feature for managing reactivity within components is the state feature.