UNPKG

marko-widgets

Version:

Module to support binding of behavior to rendered UI components rendered on the server or client

289 lines (193 loc) 6.67 kB
Marko Widgets Taglib ==================== # Custom attributes ## w-bind This attribute is used to bind a widget to a DOM element. ### Examples Bind to a JavaScript module named `./widget.js` that exports the widget definition: ```xml <div w-bind="./widget">...</div> ``` Bind to a JavaScript module named `./widget.js` or `./index.js` (searched for in that order) that exports the widget definition: ```xml <div w-bind>...</div> ``` ## w-id Used to assign a _scoped_ ID to a nested widget or a nested DOM element. The ID will be a concatenation of the parent widget ID with the provided value of the `w-id`. ### Examples #### Using `w-id` with an HTML element ```xml <div w-bind="./widget"> <button w-id="myButton" type="button">My Button</button> </div> ``` This will produce output code similar to the following: ```html <div> <button id="w0-myButton" type="button">My Button</button> </div> ``` The containing widget can reference the nested DOM element using the following code: ```javascript var myButton = this.getEl('myButton'); ``` #### Using `w-id` with a nested widget ```xml <div w-bind="./widget"> <app-button w-id="myButton" label="My Button" /> </div> ``` This will produce output code similar to the following: ```html <div> <button id="w0-myButton" type="button">My Button</button> </div> ``` The containing widget can reference the nested widget using the following code: ```javascript var myButton = this.getWidget('myButton'); ``` ## w-on* The `w-on*` can be used to declaratively bind event listeners to a DOM element or widget. NOTE: For DOM events that bubble, efficient DOM event delegation will automatically be used to avoid attaching direct event listeners for performance reasons. ### Examples #### Using `w-on*` with a nested HTML element ```xml <div w-bind="./widget"> <button w-onclick="handleMyButtonClick" type="button">My Button</button> </div> ``` When the button HTML element is clicked, the `handleMyButtonClick` method of the widget will be invoked: ```javascript module.exports = require('marko-widgets').defineComponent({ // ... handleMyButtonClick: function(event, el) { // event will be the native DOM event // el will be the native DOM element } }) ``` The containing widget can reference the nested DOM element using the following code: ```javascript var myButton = this.getEl('myButton'); ``` #### Using `w-on*` with a nested widget ```xml <div w-bind="./widget"> <app-button w-onSomeCustomEvent="handleSomeCustomEvent" label="My Button" /> </div> ``` For the example above it is assumed that the nested widget will emit the custom event using code similar to the following: ```javascript this.emit('handleSomeCustomEvent', { foo: bar }); ``` <a name="w-preserve"></a> ## w-preserve Preserves the DOM subtree associated with the DOM element or widget such that it won't be modified or rerendered when rerendering the UI component. Example: ```xml <div> <table w-preserve> <!-- Don't ever rerender this table --> ... </table> </div> ``` ```xml <div> <app-map w-preserve/> <!-- Don't ever rerender this UI component --> </div> ``` ## w-preserve-if Similar to [w-preserve](#w-preserve) except that the DOM subtree is conditionally preserved: ```xml <div> <table w-preserve-if(data.tableData == null)> ... </table> </div> ``` ## w-preserve-body Similar to [w-preserve](#w-preserve) except that only the child DOM nodes are preserved: ```xml <div w-preserve-body> <!-- Don't ever rerender any nested DOM elements --> ... </div> ``` ## w-preserve-body-if Similar to [w-preserve-if](#w-preserve) except that only the child DOM nodes are preserved: ```xml <div> <table w-preserve-if(data.tableData == null)> ... </table> </div> ``` ## w-preserve-attrs This custom attribute is used to prevent select DOM elements from being modified during a rerender: ```xml <div w-preserve-attrs="class,style"> ... </div> ``` #### w-for The `w-for` attribute is used to render a `for` attribute that references a scoped widget element: ```xml <form> <label w-for="yes">Yes</label> <input type="radio" w-id="yes" value="yes"> <label w-for="no">No</label> <input type="radio" w-id="no" value="no"> </form> ``` This will produce code similar to the following: ```html <form> <label for="w0-yes">Yes</label> <input type="radio" w-id="w0-yes" value="yes"> <label for="w0-no">No</label> <input type="radio" id="w0-no" value="no"> </form> ``` # Custom tags ## `<init-widgets>` Generates the necessary code to initialize widgets associated with UI components rendered on the _server_. Supported attributes: - __`immediate`__ - If true then a `<script>` tag will be generated that _immediately_ initializes all widgets instead of waiting for the "dom ready" event. For async fragments, a `<script>` will be inserted at the end of each async fragment. ### Examples: ### Non-immediate widget initialization If the `immediate` attribute is not provided or set to `false` then widgets will initialize during the "dom ready" event. For example, given the following Marko code: ```xml <init-widgets/> ``` This will produce output HTML code similar to the following: ```html <noscript id="markoWidgets" data-ids="w0,w1,w2"></noscript> ``` The `<noscript>` HTML tag is simply a container to keep an "index" of all of the IDs associated with UI components that have a widget that needs to be initialized. When the `marko-widgets` module initializes in the browser it will query for the `#markoWidgets` to discover all of the widget IDs. ### Immediate widget initialization If the `immediate` attribute is provided or set to `true` then widgets will initialize via inline JavaScript code added to the output HTML. For example, given the following Marko code: ```xml <init-widgets immediate/> ``` This will produce output HTML code similar to the following: ```html <script> /* REMOVED: serialized widget state and config */ $markoWidgets("w0,w1,w2") </script> ``` When immediate widget initialization is enabled, widgets will be initialized before the DOM ready event. In addition, inline widget initialization code will be appended to each async fragment. ## `<widget-types>` Used to conditionally bind a widget: ```xml <widget-types default="./widget" mobile="./widget-mobile"/> <div w-bind=(data.isMobile ? 'default' : 'mobile')> ... </div> ``` The `<widget-types>` can also be used to disabling binding of a widget: ```xml <widget-types default="./"/> <div w-bind=(data.includeWidget ? 'default' : null)> </div> ```