Two-way binding
Two-way binding is a strategy to simplify the synchronization between a JavaScript reference and the HTML element value and vice versa. That means every change in the{self}
property value reflects in the HTML element value, and every change in the HTML element value propagates back to the {self}
.
The @bind attribute
The
@bind
attribute synchronizes the {self}
property to the component or the HTML element value.
Two-way data binding examples
The following examples show how to bind simple and more complex native HTML elements, such as multiple dropdowns and checkboxes.Text input
The @bind creates a transparent event to keep the self property in sync with the value of the input text.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <div id='root'></div> <script> function Input() { // Initial state const self = this; self.input = 'Reactive'; // Two-way data binding values // Any change in the self.input will update the input and vice-versa. return `<> <h1>{{self.input}}</h1> <input type='text' @bind='self.input' /> <input type='button' value='Update' onclick="self.input = 'New value'" /> </>`; } lemonade.render(Input, document.getElementById('root')); </script> </html>
See this example on codesandbox
Checkboxes
The checkbox works similarly to the example above. The state of the checkbox and the value of the{self}
property is bound.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <div id='root'></div> <script> function Checkbox() { const self = this; self.email = true; self.phone = false; return `<> <span>Email: {{self.email}}</span><br> <span>Phone: {{self.phone}}</span><br> <fieldset> <legend>Contact options</legend> <label><input type='checkbox' @bind='self.email'/> Email</label> <label><input type='checkbox' @bind='self.phone'/> Phone</label> </fieldset> </>`; } lemonade.render(Checkbox, document.getElementById('root')); </script> </html>
See this example on codesandbox
Radio
On a radio HTML element, the self attribute should be the same so that{self}
property holds the exact value of the radio.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <div id='root'></div> <script> function Radio() { const self = this; self.favorite = 'Pears'; return `<> <fieldset> <legend>Favorite fruit</legend> <label> <input type='radio' name='favorite' value='Apples' @bind='self.favorite' /> Apples </label> <label> <input type='radio' name='favorite' value='Pears' @bind='self.favorite' /> Pears </label> <label> <input type='radio' name='favorite' value='Oranges' @bind='self.favorite' /> Oranges </label> </fieldset> <br/> <input type='button' onclick="alert(self.favorite)" value='Get' /> <input type='button' onclick="self.favorite = 'Oranges'" value='Set (Oranges)' /> </>`; } lemonade.render(Radio, document.getElementById('root')); </script> </html>
See this example on codesandbox
Multiple select
The multiple select has a different handler from other HTML elements. That is because multiple select updates an array that holds the various values.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <div id='root'></div> <script> function Multiple() { const self = this; self.options = ['John','George']; return `<> <h1>{{self.options}}</h1> <select @bind='self.options' multiple='multiple' size='10'> <option>Paul</option> <option>Ringo</option> <option>John</option> <option>George</option> </select><br/> <button onclick="self.options = ['Ringo'];">Update</button> </>`; } lemonade.render(Multiple, document.getElementById('root')); </script> </html>
See this example on codesandbox
ContentEditable
LemonadeJS will track changes and keep the{self}
property value in sync with changes in an editable div and vice versa.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <div id='root'></div> <script> function Editable() { const self = this; self.editor = 'Hello world'; return `<> <h1>Editor</h1> <p>{{self.editor}}</p> <div @bind='self.editor' contentEditable='true' style='border:1px solid black'></div><br/> <input type='button' onclick="alert(self.editor)" value="Get" /> </>`; } lemonade.render(Editable, document.getElementById('root')); </script> </html>
See this example on codesandbox
Two-way binding in custom elements
The @bind attributed to custom elements binds with the component{self}
attribute value.Basic implementation
The following example shows an implementation of @bind in custom elements.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <div id='root'></div> <script> function Test() { // This will bring all properties defined in the tag const self = this; // Custom HTML components has the self.value as default return `<b>Component value: {{self.value}}</b>`; } function Component() { const self = this; self.test = "Initial value"; return `<> <Test @bind="self.test" /><br/><br/> <input type='button' onclick="alert(self.test)" value="Get" /> <input type='button' onclick="self.test = 'Test'" value="Set" /> </>`; } // Render lemonade.setComponents({ Test }); // Render the component lemonade.render(Component, document.getElementById('root')); </script> </html>
See this example on codesandbox
Integration with custom third-party plugins
The following example shows a jSuites Tags Plugin integrated with LemonadeJS.<html> <script src="https://lemonadejs.net/v3/lemonade.js"></script> <script src="https://jsuites.net/v4/jsuites.js"></script> <link rel="stylesheet" href="https://jsuites.net/v4/jsuites.css" type="text/css" /> <div id='root'></div> <script> function Keywords() { const self = this; // Render reactive component self.create = function(o) { jSuites.tags(o); // List of keywords self.keywords = 'Oranges,pears'; } // Component reactive template return `<> <div @bind='self.keywords' @ready='self.create(this)'></div> <div>Keywords: {{self.keywords}}</div> </>`; } lemonade.render(Keywords, document.getElementById('root')); </script> </html>
The tags plugin component implements val() to integrate with LemonadeJS @bind.
See this example on codesandbox
Conclusion
In the example above, you might notice the usage of another of the native lemonade special HTML attribute:@ready
. That method call happens when the element is created and appended to the DOM.More custom-integrated custom components
For more about other components, please visit the javascript plugins website.Next chapter: Dealing with arrays and loops