mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Merge pull request #510 from austinkelleher/421-deprecate-w-bind
Fixes #421 - Deprecate w-bind
This commit is contained in:
commit
023e5a4ca8
@ -261,7 +261,7 @@ module.exports = require('marko-widgets').defineComponent({
|
||||
And, here is the corresponding Marko template for the UI component:
|
||||
|
||||
```xml
|
||||
<div class="click-count" w-bind>
|
||||
<div class="click-count">
|
||||
Hello ${data.greetingName}!
|
||||
<div>
|
||||
You clicked the button ${data.clickCount} ${data.timesMessage}.
|
||||
|
||||
@ -30,18 +30,11 @@ A few definitions before you get started:
|
||||
|
||||
## Binding Behavior
|
||||
|
||||
Using the bindings for Marko, you can bind a widget to a rendered DOM element using the custom `w-bind` attribute as shown in the following sample template:
|
||||
Marko will search for a widget module by first checking to see if `widget.js`
|
||||
exists and then `index.js` and automatically bind accordingly. Example:
|
||||
|
||||
```xml
|
||||
<div class="my-component" w-bind="./widget">
|
||||
<div>Click Me</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can also choose to leave the value of the `w-bind` attribute empty. If the value of `w-bind` is empty then `marko-widgets` will search for a widget module by first checking to see if `widget.js` exists and then `index.js`. Example:
|
||||
|
||||
```xml
|
||||
<div class="my-component" w-bind>
|
||||
<div class="my-component">
|
||||
<div>Click Me</div>
|
||||
</div>
|
||||
```
|
||||
@ -193,7 +186,7 @@ The `marko-widgets` taglib also provides support for allowing a widget to commun
|
||||
The following HTML template fragment contains a widget that has three nested [sample-button](https://github.com/marko-js-samples/marko-sample-components/tree/master/components/sample-button) widgets. Each nested [sample-button](https://github.com/marko-js-samples/marko-sample-components/tree/master/components/sample-button) is assigned an ID (i.e. `primaryButton`, `successButton` and `dangerButton`).
|
||||
|
||||
```xml
|
||||
<div class="my-component" w-bind="./widget">
|
||||
<div class="my-component">
|
||||
<div class="btn-group">
|
||||
<sample-button label="Click Me" variant="primary" ref="primaryButton"/>
|
||||
<sample-button label="Click Me" variant="success" ref="successButton"/>
|
||||
@ -214,7 +207,7 @@ this.getWidget('dangerButton').on('click', function() {
|
||||
Marko Widgets also supports referencing _repeated_ nested widgets as shown below:
|
||||
|
||||
```xml
|
||||
<div class="my-component" w-bind="./widget">
|
||||
<div class="my-component">
|
||||
<ul>
|
||||
<li for="todoItem in data.todoItems">
|
||||
<app-todo-item ref="todoItems[]" todo-item="todoItem"/>
|
||||
@ -237,7 +230,7 @@ To try out and experiment with this code please see the documentation and source
|
||||
DOM elements nested within a widget can be given unique IDs based on the containing widget's ID. These DOM elements can then be efficiently looked up by the containing widget using methods provided. The `ref` custom attribute can be used to assign DOM element IDs to HTML elements that are prefixed with the widget's ID. For example, given the following HTML template fragment:
|
||||
|
||||
```xml
|
||||
<form w-bind="./widget">
|
||||
<form>
|
||||
...
|
||||
<button type="submit" ref="submitButton">Submit</button>
|
||||
<button type="button" ref="cancelButton">Cancel</button>
|
||||
@ -307,11 +300,11 @@ A widget can subscribe to events on a nested DOM element.
|
||||
Listeners can be attached declaratively as shown in the following sample code:
|
||||
|
||||
```xml
|
||||
<div w-bind>
|
||||
<form onsubmit("handleFormSubmit")>
|
||||
<input type="text" value="email" onchange("handleEmailChange")>
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
<div>
|
||||
<form onsubmit("handleFormSubmit")>
|
||||
<input type="text" value="email" onchange("handleEmailChange")>
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -350,7 +343,7 @@ For performance reasons, Marko Widgets only adds one event listener to the root
|
||||
You can also choose to add listeners in JavaScript code by assigning an "element id" to the nested DOM element (only needs to be unique within the scope of the containing widget) so that the nested DOM element can be referenced by the containing widget. The scoped widget element ID should be assigned using the `ref="<id>"` attribute. For example, in the template:
|
||||
|
||||
```xml
|
||||
<div w-bind>
|
||||
<div>
|
||||
<form ref="form">
|
||||
<input type="text" value="email" ref="email">
|
||||
<button>Submit</button>
|
||||
@ -404,7 +397,7 @@ A widget can subscribe to events on nested widgets. Every widget extends [EventE
|
||||
Listeners can be attached declaratively as shown in the following sample code:
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<div>
|
||||
<app-overlay title="My Overlay"
|
||||
onBeforeHide("handleOverlayBeforeHide")>
|
||||
|
||||
@ -429,7 +422,7 @@ module.exports = require('marko-widgets').defineComponent({
|
||||
You can also choose to add listeners in JavaScript code by assigning an "id" to the nested widget (only needs to be unique within the scope of the containing widget) so that the nested widget can be referenced by the containing widget. The scoped widget ID should be assigned using the `ref="<id>"` attribute. For example, in the template:
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<div>
|
||||
<app-overlay title="My Overlay"
|
||||
ref="myOverlay">
|
||||
|
||||
@ -583,7 +576,7 @@ __src/pages/index/template.marko:__
|
||||
<body>
|
||||
<div>Marko Widgets: Bind</div>
|
||||
|
||||
<div class="my-component" w-bind="./widget">
|
||||
<div class="my-component">
|
||||
<div>Click Me</div>
|
||||
</div>
|
||||
|
||||
@ -698,9 +691,8 @@ src/components/app-hello/
|
||||
___src/components/app-hello/template.marko:___
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
on-click("handleClick")>
|
||||
Hello ${data.name}!
|
||||
<div on-click("handleClick")>
|
||||
Hello ${data.name}!
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -735,9 +727,8 @@ src/components/app-hello/
|
||||
___src/components/app-hello/template.marko:___
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget"
|
||||
on-click("handleClick")>
|
||||
Hello ${data.name}!
|
||||
<div on-click("handleClick")>
|
||||
Hello ${data.name}!
|
||||
</div>
|
||||
```
|
||||
|
||||
|
||||
@ -58,7 +58,7 @@ Marko Widgets allows you to declaratively bind behavior to an HTML element insid
|
||||
__src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind>
|
||||
<div>
|
||||
Hello ${data.name}!
|
||||
</div>
|
||||
```
|
||||
@ -112,11 +112,8 @@ widget.setProps({
|
||||
__src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
onClick("handleClick")>
|
||||
|
||||
Hello ${data.name}!
|
||||
|
||||
<div onClick("handleClick")>
|
||||
Hello ${data.name}!
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -153,7 +150,7 @@ Let's create a stateful widget that changes to yellow when you click on it:
|
||||
__src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
<div
|
||||
onClick("handleClick")
|
||||
style="background-color: ${data.color}">
|
||||
|
||||
@ -201,7 +198,7 @@ If you want to avoid re-rendering a widget for a particular state property chang
|
||||
__src/components/app-hello/template.marko__
|
||||
|
||||
```xml
|
||||
<div w-bind
|
||||
<div
|
||||
onClick("handleClick")
|
||||
style="background-color: ${data.color}">
|
||||
|
||||
@ -255,7 +252,7 @@ module.exports = require('marko-widgets').defineComponent({
|
||||
## Complex Widget
|
||||
|
||||
```xml
|
||||
<div w-bind>
|
||||
<div>
|
||||
<app-overlay title="My Overlay"
|
||||
ref="overlay"
|
||||
onBeforeHide("handleOverlayBeforeHide")>
|
||||
@ -309,7 +306,7 @@ A container widget supports nested content. When the container widget is re-rend
|
||||
__src/components/app-alert/template.marko__
|
||||
|
||||
```xml
|
||||
<div class="alert alert-${data.type}" w-bind>
|
||||
<div class="alert alert-${data.type}">
|
||||
<i class="alert-icon"/>
|
||||
<span w-body></span>
|
||||
</div>
|
||||
@ -376,7 +373,7 @@ Sometimes it is important to _not_ re-render a DOM subtree. This may due to eith
|
||||
Marko Widgets allows DOM nodes to be preserved by putting a special `no-update`, `no-update-if(<condition>)`, `no-update-body` or `no-update-body-if(<condition>)` attribute on the HTML tags that should be preserved. Preserved DOM nodes will be reused and re-inserted into a widget's newly rendered DOM automatically.
|
||||
|
||||
```xml
|
||||
<div w-bind>
|
||||
<div>
|
||||
|
||||
<span no-update>
|
||||
<p>
|
||||
|
||||
@ -3,24 +3,6 @@ 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>
|
||||
```
|
||||
|
||||
## ref
|
||||
|
||||
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 `ref`.
|
||||
@ -31,7 +13,7 @@ Used to assign a _scoped_ ID to a nested widget or a nested DOM element. The ID
|
||||
#### Using `ref` with an HTML element
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<div>
|
||||
<button ref="myButton" type="button">My Button</button>
|
||||
</div>
|
||||
```
|
||||
@ -54,7 +36,7 @@ var myButton = this.getEl('myButton');
|
||||
#### Using `ref` with a nested widget
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<div>
|
||||
<app-button ref="myButton" label="My Button" />
|
||||
</div>
|
||||
```
|
||||
@ -84,7 +66,7 @@ NOTE: For DOM events that bubble, efficient DOM event delegation will automatica
|
||||
#### Using `w-on*` with a nested HTML element
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<div>
|
||||
<button onClick("handleMyButtonClick") type="button">My Button</button>
|
||||
</div>
|
||||
```
|
||||
@ -112,7 +94,7 @@ var myButton = this.getEl('myButton');
|
||||
#### Using `w-on*` with a nested widget
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<div>
|
||||
<app-button onSomeCustomEvent("handleSomeCustomEvent") label="My Button" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -3,5 +3,5 @@ var expect = require('chai').expect;
|
||||
module.exports = function(helpers) {
|
||||
expect(function() {
|
||||
require('./template.marko');
|
||||
}).to.throw(/Invalid "w-bind" attribute/);
|
||||
}).to.throw(/No corresponding JavaScript module found in the same directory/);
|
||||
};
|
||||
@ -199,7 +199,7 @@ module.exports = function handleRootNodes() {
|
||||
var nextRef = 0;
|
||||
|
||||
rootNodes.forEach((curNode, i) => {
|
||||
curNode.setAttributeValue('w-bind');
|
||||
curNode.setAttributeValue('_widgetbind');
|
||||
|
||||
if (!curNode.hasAttribute('ref')) {
|
||||
if (curNode.type === 'CustomTag' || rootNodes.length > 1) {
|
||||
|
||||
@ -57,13 +57,23 @@ module.exports = function handleWidgetBind() {
|
||||
let context = this.context;
|
||||
let builder = this.builder;
|
||||
|
||||
let internalBindAttr = el.getAttribute('_widgetbind');
|
||||
let bindAttr = el.getAttribute('w-bind');
|
||||
if (bindAttr == null) {
|
||||
return;
|
||||
}
|
||||
let bindAttrValue;
|
||||
|
||||
// Remove the w-bind attribute since we don't want it showing up in the output DOM
|
||||
el.removeAttribute('w-bind');
|
||||
if (internalBindAttr == null && bindAttr == null) {
|
||||
return;
|
||||
} else if (bindAttr != null) {
|
||||
context.deprecate('The "w-bind" attribute is deprecated. Please remove it. See: https://github.com/marko-js/marko/issues/421');
|
||||
|
||||
// Remove the w-bind attribute since we don't want it showing up in the output DOM
|
||||
el.removeAttribute('w-bind');
|
||||
|
||||
// Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript
|
||||
bindAttrValue = bindAttr.value;
|
||||
} else if (internalBindAttr != null) {
|
||||
el.removeAttribute('_widgetbind');
|
||||
}
|
||||
|
||||
var isInnerBind = checkIsInnerBind(el.parentNode);
|
||||
|
||||
@ -71,8 +81,6 @@ module.exports = function handleWidgetBind() {
|
||||
|
||||
// A widget is bound to the el...
|
||||
|
||||
// Read the value for the w-bind attribute. This will be an AST node for the parsed JavaScript
|
||||
let bindAttrValue = bindAttr.value;
|
||||
let modulePath;
|
||||
|
||||
var widgetProps = isInnerBind ? {} : this.getWidgetProps();
|
||||
@ -92,7 +100,7 @@ module.exports = function handleWidgetBind() {
|
||||
} else {
|
||||
modulePath = this.getDefaultWidgetModule();
|
||||
if (!modulePath) {
|
||||
this.addError('Invalid "w-bind" attribute. No corresponding JavaScript module found in the same directory (either "widget.js" or "index.js"). Actual: ' + modulePath);
|
||||
this.addError('No corresponding JavaScript module found in the same directory (either "widget.js" or "index.js"). Actual: ' + modulePath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ module.exports = function transform(el, context) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (el.hasAttribute('w-bind')) {
|
||||
if (el.hasAttribute('_widgetbind') || el.hasAttribute('w-bind')) {
|
||||
el.setFlag('hasWidgetBind');
|
||||
transformHelper.handleWidgetBind();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user