mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Introduce "ref" and "for-ref" attributes
Deprecated "w-id" and "w-for"
This commit is contained in:
parent
00b52ae5be
commit
e1940a7ff0
@ -685,7 +685,7 @@ Or, since `widget.js` is automatically recognized
|
||||
</div>
|
||||
```
|
||||
|
||||
### Deprecate `w-id` and `w-for` in favor of `ref` and `ref-for` ([#394](https://github.com/marko-js/marko/issues/394))
|
||||
### Deprecate `w-id` and `w-for` in favor of `ref` and `for-ref` ([#394](https://github.com/marko-js/marko/issues/394))
|
||||
|
||||
The `w-id` attribute was used to obtain references using `this.getEl(refId)`. `w-id` has been replaced with the `ref` attribute:
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ Marko Widgets starts a batch when handling a bubbling a DOM event that came off
|
||||
|
||||
# How do widgets communicate?
|
||||
|
||||
Every widget is an [EventEmitter](https://nodejs.org/api/events.html#events_class_events_eventemitter) instance and widgets typically communicate by emitting custom events that can then be handled by the direct parent of the widget. The parent widget can choose to handle the event or emit another custom event that bubbles up to its parent. A widget should only communicate directly with nested widgets that it "owns" (i.e., nested widgets that were introduced in the containing widget's template). A widget can get a direct reference to a nested widget using the `this.getWidget(nestedWidgetId)` method (where `nestedWidgetId` is the ID assigned using the `w-id` attribute).
|
||||
Every widget is an [EventEmitter](https://nodejs.org/api/events.html#events_class_events_eventemitter) instance and widgets typically communicate by emitting custom events that can then be handled by the direct parent of the widget. The parent widget can choose to handle the event or emit another custom event that bubbles up to its parent. A widget should only communicate directly with nested widgets that it "owns" (i.e., nested widgets that were introduced in the containing widget's template). A widget can get a direct reference to a nested widget using the `this.getWidget(nestedWidgetId)` method (where `nestedWidgetId` is the ID assigned using the `ref` attribute).
|
||||
|
||||
In some situations, it may be helpful to communicate an event on a global pub/sub channel. Pub/sub can be helpful in situations where it would overkill for an event to have to bubble up a complex widget hierarchy in order for it to be handled. The [raptor-pubsub](https://github.com/raptorjs/raptor-pubsub) module provides a very simple pub/sub implementation based on the [EventEmitter](https://nodejs.org/api/events.html#events_class_events_eventemitter) API.
|
||||
|
||||
|
||||
@ -195,9 +195,9 @@ The following HTML template fragment contains a widget that has three nested [sa
|
||||
```xml
|
||||
<div class="my-component" w-bind="./widget">
|
||||
<div class="btn-group">
|
||||
<sample-button label="Click Me" variant="primary" w-id="primaryButton"/>
|
||||
<sample-button label="Click Me" variant="success" w-id="successButton"/>
|
||||
<sample-button label="Click Me" variant="danger" w-id="dangerButton"/>
|
||||
<sample-button label="Click Me" variant="primary" ref="primaryButton"/>
|
||||
<sample-button label="Click Me" variant="success" ref="successButton"/>
|
||||
<sample-button label="Click Me" variant="danger" ref="dangerButton"/>
|
||||
</div>
|
||||
...
|
||||
</div>
|
||||
@ -217,7 +217,7 @@ Marko Widgets also supports referencing _repeated_ nested widgets as shown below
|
||||
<div class="my-component" w-bind="./widget">
|
||||
<ul>
|
||||
<li for="todoItem in data.todoItems">
|
||||
<app-todo-item w-id="todoItems[]" todo-item="todoItem"/>
|
||||
<app-todo-item ref="todoItems[]" todo-item="todoItem"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -234,13 +234,13 @@ To try out and experiment with this code please see the documentation and source
|
||||
|
||||
## Referencing Nested DOM Elements
|
||||
|
||||
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 `w-id` 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:
|
||||
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">
|
||||
...
|
||||
<button type="submit" w-id="submitButton">Submit</button>
|
||||
<button type="button" w-id="cancelButton">Cancel</button>
|
||||
<button type="submit" ref="submitButton">Submit</button>
|
||||
<button type="button" ref="cancelButton">Cancel</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
@ -283,7 +283,7 @@ Marko Widgets also supports referencing _repeated_ nested DOM elements as shown
|
||||
```xml
|
||||
<ul>
|
||||
<li for="color in ['red', 'green', 'blue']"
|
||||
w-id="colorListItems[]">
|
||||
ref="colorListItems[]">
|
||||
$color
|
||||
</li>
|
||||
</ul>
|
||||
@ -347,12 +347,12 @@ NOTE: Event handler methods will be invoked with `this` being the widget instanc
|
||||
|
||||
For performance reasons, Marko Widgets only adds one event listener to the root `document.body` element for each event type that bubbles. When Marko Widgets captures an event on `document.body` it will internally delegate the event to the appropriate widgets. For DOM events that do not bubble, Marko Widgets will automatically add DOM event listeners to each of the DOM nodes. If a widget is destroyed, Marko Widgets will automatically do the appropriate cleanup to remove DOM event listeners.
|
||||
|
||||
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 `w-id="<id>"` attribute. For example, in the template:
|
||||
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>
|
||||
<form w-id="form">
|
||||
<input type="text" value="email" w-id="email">
|
||||
<form ref="form">
|
||||
<input type="text" value="email" ref="email">
|
||||
<button>Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
@ -426,12 +426,12 @@ 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 `w-id="<id>"` attribute. For example, in the template:
|
||||
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">
|
||||
<app-overlay title="My Overlay"
|
||||
w-id="myOverlay">
|
||||
ref="myOverlay">
|
||||
|
||||
Content for overlay
|
||||
|
||||
|
||||
@ -257,7 +257,7 @@ module.exports = require('marko-widgets').defineComponent({
|
||||
```xml
|
||||
<div w-bind>
|
||||
<app-overlay title="My Overlay"
|
||||
w-id="overlay"
|
||||
ref="overlay"
|
||||
w-onBeforeHide="handleOverlayBeforeHide">
|
||||
Body content for overlay.
|
||||
</app-overlay>
|
||||
|
||||
@ -21,18 +21,18 @@ Bind to a JavaScript module named `./widget.js` or `./index.js` (searched for in
|
||||
<div w-bind>...</div>
|
||||
```
|
||||
|
||||
## w-id
|
||||
## 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 `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 `ref`.
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
#### Using `w-id` with an HTML element
|
||||
#### Using `ref` with an HTML element
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<button w-id="myButton" type="button">My Button</button>
|
||||
<button ref="myButton" type="button">My Button</button>
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -51,11 +51,11 @@ The containing widget can reference the nested DOM element using the following c
|
||||
var myButton = this.getEl('myButton');
|
||||
```
|
||||
|
||||
#### Using `w-id` with a nested widget
|
||||
#### Using `ref` with a nested widget
|
||||
|
||||
```xml
|
||||
<div w-bind="./widget">
|
||||
<app-button w-id="myButton" label="My Button" />
|
||||
<app-button ref="myButton" label="My Button" />
|
||||
</div>
|
||||
```
|
||||
|
||||
@ -196,10 +196,10 @@ The `w-for` attribute is used to render a `for` attribute that references a scop
|
||||
```xml
|
||||
<form>
|
||||
<label w-for="yes">Yes</label>
|
||||
<input type="radio" w-id="yes" value="yes">
|
||||
<input type="radio" ref="yes" value="yes">
|
||||
|
||||
<label w-for="no">No</label>
|
||||
<input type="radio" w-id="no" value="no">
|
||||
<input type="radio" ref="no" value="no">
|
||||
</form>
|
||||
```
|
||||
|
||||
@ -208,7 +208,7 @@ 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">
|
||||
<input type="radio" ref="w0-yes" value="yes">
|
||||
|
||||
<label for="w0-no">No</label>
|
||||
<input type="radio" id="w0-no" value="no">
|
||||
|
||||
@ -15,7 +15,7 @@ Upgrade Guide
|
||||
- Integrated [morphdom](https://github.com/patrick-steele-idem/morphdom) to more efficiently transform the existing DOM instead of replacing it entirely
|
||||
- Significant performance improvements
|
||||
- Code cleanup
|
||||
- Stable IDs for widgets that are not assigned a `w-id`
|
||||
- Stable IDs for widgets that are not assigned a `ref`
|
||||
- New lifecycle event: 'onRender'
|
||||
|
||||
## v3 to v4
|
||||
@ -176,4 +176,4 @@ _New renderer.js:_
|
||||
exports.renderer = function(input, out) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
"w-scope",
|
||||
"w-extend",
|
||||
"w-config",
|
||||
"for-ref",
|
||||
"ref",
|
||||
"w-for",
|
||||
"w-id",
|
||||
"w-body",
|
||||
@ -23,4 +25,4 @@
|
||||
"w-preserve-body-if",
|
||||
"w-preserve-attrs",
|
||||
"w-on*"
|
||||
]
|
||||
]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<div w-bind>
|
||||
<div.unpreserved-counter>${data.counter}</div>
|
||||
<span w-id="preserve" data-counter=data.counter w-preserve-body>
|
||||
<span ref="preserve" data-counter=data.counter w-preserve-body>
|
||||
<div.preserved-counter>${data.counter}</div>
|
||||
</span>
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
<div w-bind>
|
||||
<div.unpreserved-counter>${data.counter}</div>
|
||||
<span w-id="preserve" data-counter=data.counter w-preserve>
|
||||
<span ref="preserve" data-counter=data.counter w-preserve>
|
||||
<div.preserved-counter>${data.counter}</div>
|
||||
</span>
|
||||
</div>
|
||||
@ -1,3 +1,3 @@
|
||||
<div w-bind>
|
||||
Hello <span w-id="name">${data.name}</span>!
|
||||
Hello <span ref="name">${data.name}</span>!
|
||||
</div>
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<div class="foo" w-bind="./widget">
|
||||
<app-bar w-id="bar"/>
|
||||
<app-bar w-id="bar2"/>
|
||||
<app-bar ref="bar"/>
|
||||
<app-bar ref="bar2"/>
|
||||
|
||||
<app-bar w-id="barArray[]" label="1"/>
|
||||
<app-bar w-id="barArray[]" label="2"/>
|
||||
<app-bar ref="barArray[]" label="1"/>
|
||||
<app-bar ref="barArray[]" label="2"/>
|
||||
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" w-id="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" ref="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent2" channel="customEvents-${widget.id}" />
|
||||
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) w-id="colorListItems[]">${color}</li>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<span class="config" w-id="config"></span>
|
||||
<span class="config" ref="config"></span>
|
||||
</div>
|
||||
@ -1,17 +1,17 @@
|
||||
<div class="foo" w-bind="./widget">
|
||||
<app-bar w-id="bar"/>
|
||||
<app-bar w-id="bar2"/>
|
||||
<app-bar ref="bar"/>
|
||||
<app-bar ref="bar2"/>
|
||||
|
||||
<app-bar w-id="barArray[]" label="1"/>
|
||||
<app-bar w-id="barArray[]" label="2"/>
|
||||
<app-bar ref="barArray[]" label="1"/>
|
||||
<app-bar ref="barArray[]" label="2"/>
|
||||
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" w-id="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" ref="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent2" channel="customEvents-${widget.id}" />
|
||||
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) w-id="colorListItems[]">${color}</li>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<span class="config" w-id="config"></span>
|
||||
<span class="config" ref="config"></span>
|
||||
</div>
|
||||
@ -1,17 +1,17 @@
|
||||
<div class="foo" w-bind="./widget">
|
||||
<app-bar w-id="bar"/>
|
||||
<app-bar w-id="bar2"/>
|
||||
<app-bar ref="bar"/>
|
||||
<app-bar ref="bar2"/>
|
||||
|
||||
<app-bar w-id="barArray[]" label="1"/>
|
||||
<app-bar w-id="barArray[]" label="2"/>
|
||||
<app-bar ref="barArray[]" label="1"/>
|
||||
<app-bar ref="barArray[]" label="2"/>
|
||||
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" w-id="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent1" ref="customEvents" />
|
||||
<app-custom-events w-onTestEvent="handleTestEvent2" channel="customEvents-${widget.id}" />
|
||||
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) w-id="colorListItems[]">${color}</li>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<span class="config" w-id="config"></span>
|
||||
<span class="config" ref="config"></span>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
<app-legacy-button size="small" w-id="button1">button1</app-legacy-button>
|
||||
<app-legacy-button size="normal" w-id="button2">button2</app-legacy-button>
|
||||
<app-legacy-button size="small" ref="button1">button1</app-legacy-button>
|
||||
<app-legacy-button size="normal" ref="button2">button2</app-legacy-button>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
<app-legacy-button size="small" w-id="button1">button1</app-legacy-button>
|
||||
<app-legacy-button size="normal" w-id="button2">button2</app-legacy-button>
|
||||
<app-legacy-button size="small" ref="button1">button1</app-legacy-button>
|
||||
<app-legacy-button size="normal" ref="button2">button2</app-legacy-button>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
<a href="#foo" w-id="fooLink"
|
||||
<a href="#foo" ref="fooLink"
|
||||
w-ondblclick="handleFooLinkDblClick"
|
||||
w-onmouseout="handleFooLinkMouseOut">
|
||||
</a>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="app-discard" w-bind>
|
||||
[app-discard]
|
||||
<app-simple name="John" message-count=50 w-id="simple" if(data.showSimple)/>
|
||||
<app-simple name="John" message-count=50 ref="simple" if(data.showSimple)/>
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
<div w-bind>
|
||||
<ul>
|
||||
<li w-onMouseMove="handleMouseMove" w-id="foo-${loop.getIndex()}"
|
||||
<li w-onMouseMove="handleMouseMove" ref="foo-${loop.getIndex()}"
|
||||
for(color in ['red', 'green', 'blue'] | status-var=loop)>${color}</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -1,2 +1,2 @@
|
||||
div class="app-dom-events-jquery" w-bind="./widget"
|
||||
button type="button" w-id="button" - Button
|
||||
button type="button" ref="button" - Button
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
w-bind="./widget"
|
||||
w-onmousemove="handleRootMouseMove"
|
||||
w-onClick="handleRootClick">
|
||||
<button type="button" w-id="button"
|
||||
<button type="button" ref="button"
|
||||
w-onclick="handleButtonClick">
|
||||
<span w-onmousemove="handleButtonSpanMouseMove">
|
||||
Button
|
||||
@ -14,7 +14,7 @@
|
||||
w-onmouseout="handleFooLinkMouseOut">
|
||||
</a>
|
||||
|
||||
<app-legacy-button w-id="appButton">
|
||||
<span w-id="helloWorld" w-onmousedown="handleHelloWorldMouseDown">Hello World</span>
|
||||
<app-legacy-button ref="appButton">
|
||||
<span ref="helloWorld" w-onmousedown="handleHelloWorldMouseDown">Hello World</span>
|
||||
</app-legacy-button>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
<input w-onclick=(false && 'handleButtonClick') w-id="inputWithoutHandler" type="button">
|
||||
<input w-onclick=(true && 'handleButtonClick') w-id="inputWithHandler" type="button">
|
||||
<input w-onclick='handleButtonClick' w-id="inputWithLiteralHandler" type="button">
|
||||
<input w-onclick=(false && 'handleButtonClick') ref="inputWithoutHandler" type="button">
|
||||
<input w-onclick=(true && 'handleButtonClick') ref="inputWithHandler" type="button">
|
||||
<input w-onclick='handleButtonClick' ref="inputWithLiteralHandler" type="button">
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
<input w-onMouseMove=(false && "handleMouseMove") w-id="inputWithoutHandler" type="button">
|
||||
<input w-onMouseMove=(true && 'handleMouseMove') w-id="inputWithHandler" type="button">
|
||||
<input w-onMouseMove='handleMouseMove' w-id="inputWithLiteralHandler" type="button">
|
||||
<input w-onMouseMove=(false && "handleMouseMove") ref="inputWithoutHandler" type="button">
|
||||
<input w-onMouseMove=(true && 'handleMouseMove') ref="inputWithHandler" type="button">
|
||||
<input w-onMouseMove='handleMouseMove' ref="inputWithLiteralHandler" type="button">
|
||||
</div>
|
||||
@ -1,7 +1,7 @@
|
||||
<div w-bind>
|
||||
<h1>app-macro-events</h1>
|
||||
<macro renderButton(id, label, handler)>
|
||||
<button w-id="${id}" type="button" w-onClick="${handler}">
|
||||
<button ref="${id}" type="button" w-onClick="${handler}">
|
||||
$label
|
||||
</button>
|
||||
</macro>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
w-bind="./widget">
|
||||
|
||||
<if(data.label)>
|
||||
<span w-id="label">${data.label}</span>
|
||||
<span ref="label">${data.label}</span>
|
||||
</if>
|
||||
<invoke data.renderBody(out, widget)
|
||||
else-if(data.renderBody)/>
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
name=data.name
|
||||
w-extend="./widget">
|
||||
|
||||
<span class="app-checkbox-icon"/><span w-id="label">${data.label}</span>
|
||||
<span class="app-checkbox-icon"/><span ref="label">${data.label}</span>
|
||||
|
||||
</app-extend-button>
|
||||
@ -1,4 +1,4 @@
|
||||
div w-bind
|
||||
span.foo w-id="foo"
|
||||
span.bar w-id="bar"
|
||||
span.foo-bar w-id="foo-bar"
|
||||
span.foo ref="foo"
|
||||
span.bar ref="bar"
|
||||
span.foo-bar ref="foo-bar"
|
||||
@ -1,4 +1,4 @@
|
||||
div w-bind
|
||||
<ul>
|
||||
<li for(color in ['red', 'green', 'blue']) w-id="colorListItems[]">${color}</li>
|
||||
<li for(color in ['red', 'green', 'blue']) ref="colorListItems[]">${color}</li>
|
||||
</ul>
|
||||
@ -1,2 +1,2 @@
|
||||
div w-bind
|
||||
app-foo w-id="bar"
|
||||
app-foo ref="bar"
|
||||
@ -1,3 +1,3 @@
|
||||
div w-bind
|
||||
app-foo name="a" w-id="bar[]"
|
||||
app-foo name="b" w-id="bar[]"
|
||||
app-foo name="a" ref="bar[]"
|
||||
app-foo name="b" ref="bar[]"
|
||||
@ -1,2 +1,2 @@
|
||||
div w-bind
|
||||
app-foo w-id="bar[]"
|
||||
app-foo ref="bar[]"
|
||||
@ -1,3 +1,3 @@
|
||||
<div class="app-invoke-widget-id" w-bind>
|
||||
<invoke data.barRenderer({}, out) w-id=data.barWidgetId />
|
||||
<invoke data.barRenderer({}, out) ref=data.barWidgetId />
|
||||
</div>
|
||||
@ -1,3 +1,3 @@
|
||||
<div class="app-invoke-widget-id" w-bind>
|
||||
<invoke data.barRenderer({}, out) w-id="barTest"/>
|
||||
<invoke data.barRenderer({}, out) ref="barTest"/>
|
||||
</div>
|
||||
@ -1,8 +1,8 @@
|
||||
<div class="app-jquery-proxy" w-bind>
|
||||
<span w-id="foo">foo</span>
|
||||
<span w-id="foo-text">foo-text</span>
|
||||
<span w-id="fooText">fooText</span>
|
||||
<ul w-id="ul">
|
||||
<span ref="foo">foo</span>
|
||||
<span ref="foo-text">foo-text</span>
|
||||
<span ref="fooText">fooText</span>
|
||||
<ul ref="ul">
|
||||
<li>red</li>
|
||||
<li>green</li>
|
||||
<li>blue</li>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
<label w-id="label" w-for="input">foo</label>
|
||||
<input w-id="input" value="test">
|
||||
<label ref="label" for-ref="input">foo</label>
|
||||
<input ref="input" value="test">
|
||||
</div>
|
||||
|
||||
@ -8,5 +8,5 @@ module.exports = function(helpers) {
|
||||
|
||||
expect(forElId).to.exist;
|
||||
expect(inputEl.value).to.equal('test');
|
||||
expect(label.getAttribute('w-for')).to.equal(null);
|
||||
};
|
||||
expect(label.getAttribute('for-ref')).to.equal(null);
|
||||
};
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
<div w-bind>
|
||||
You have <span w-id="messageCount">${data.messageCount}</span> new messages.
|
||||
You have <span ref="messageCount">${data.messageCount}</span> new messages.
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}!
|
||||
|
||||
<app-stateful-lifecycle-events-nested w-id="nestedStateful" message-count=data.messageCount/>
|
||||
<app-stateful-lifecycle-events-nested ref="nestedStateful" message-count=data.messageCount/>
|
||||
<app-stateful-lifecycle-events-nested name="foo" message-count=data.messageCount/>
|
||||
</div>
|
||||
@ -2,6 +2,6 @@
|
||||
<a href="http://www.ebay.com" w-preserve-attrs="href">
|
||||
eBay
|
||||
</a>
|
||||
<span w-id="hello">Hello ${data.name}!</span>
|
||||
<span w-id="hello2" w-preserve-attrs="class" class="foo">Hello ${data.name}!</span>
|
||||
<span ref="hello">Hello ${data.name}!</span>
|
||||
<span ref="hello2" w-preserve-attrs="class" class="foo">Hello ${data.name}!</span>
|
||||
</div>
|
||||
@ -1,10 +1,10 @@
|
||||
<div w-bind>
|
||||
<h1>Preserve Begin</h1>
|
||||
<span w-id="preserve" w-preserve-if(data.preserveCondition) data-renderId=data.renderId>${data.renderId}</span>
|
||||
<span ref="preserve" w-preserve-if(data.preserveCondition) data-renderId=data.renderId>${data.renderId}</span>
|
||||
|
||||
<span w-id="preserveBody" w-preserve-body-if(data.preserveCondition) data-renderId=data.renderId>${data.renderId}</span>
|
||||
<span ref="preserveBody" w-preserve-body-if(data.preserveCondition) data-renderId=data.renderId>${data.renderId}</span>
|
||||
|
||||
<app-stateful-rerender w-id="widget" name=(data.renderId.toString()) w-preserve-if(data.preserveCondition) />
|
||||
<app-stateful-rerender ref="widget" name=(data.renderId.toString()) w-preserve-if(data.preserveCondition) />
|
||||
|
||||
<!-- Test without an ID -->
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
<input w-id="input" type="text" value="test" />
|
||||
<button w-id="button" />
|
||||
<app-iframe-more-content w-id="more" />
|
||||
<input ref="input" type="text" value="test" />
|
||||
<button ref="button" />
|
||||
<app-iframe-more-content ref="more" />
|
||||
</div>
|
||||
@ -1,3 +1,3 @@
|
||||
<div w-bind>
|
||||
<input w-id="input" type="text" value="hello" />
|
||||
<input ref="input" type="text" value="hello" />
|
||||
</div>
|
||||
@ -1,3 +1,3 @@
|
||||
<div class="foo" w-bind>
|
||||
<iframe w-id="frame"></iframe>
|
||||
<iframe ref="frame"></iframe>
|
||||
</div>
|
||||
@ -1,3 +1,3 @@
|
||||
<div w-bind>
|
||||
Hello <span w-id="name">${data.name}</span>!
|
||||
Hello <span ref="name">${data.name}</span>!
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div class="app-repeated-id-widgetless" w-bind>
|
||||
<for(renderer in data.renderers)>
|
||||
<invoke renderer({}, out) w-id="childWidget[]" />
|
||||
<invoke renderer({}, out) ref="childWidget[]" />
|
||||
</for>
|
||||
</div>
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind>
|
||||
[app-rerender-init-order]
|
||||
<app-rerender-init-order-child w-id="childA" id="childA" version=data.version/>
|
||||
<app-rerender-init-order-child w-id="childB" id="childB" version=data.version/>
|
||||
<app-rerender-init-order-child ref="childA" id="childA" version=data.version/>
|
||||
<app-rerender-init-order-child ref="childB" id="childB" version=data.version/>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="app-stateful-reuse-widgets" w-bind>
|
||||
<app-stateful-button size=data.buttonSize w-id="button1">${data.buttonSize}</app-stateful-button>
|
||||
<app-stateful-button size="large" w-id="button2">button2</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize ref="button1">${data.buttonSize}</app-stateful-button>
|
||||
<app-stateful-button size="large" ref="button2">button2</app-stateful-button>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,2 +1,2 @@
|
||||
<app-stateful-button label="Submit" w-id="submitButton"/>
|
||||
<app-stateful-button label="Cancel" w-id="cancelButton"/>
|
||||
<app-stateful-button label="Submit" ref="submitButton"/>
|
||||
<app-stateful-button label="Cancel" ref="cancelButton"/>
|
||||
@ -1,3 +1,3 @@
|
||||
<div class="app-stateful-preserve-body" w-bind>
|
||||
<app-stateful-button size="large" w-id="button1">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size="large" ref="button1">${data.buttonLabel}</app-stateful-button>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="app-stateful-reuse-widgets" w-bind>
|
||||
<app-stateful-button size=data.buttonSize w-id="button1">${data.buttonSize}</app-stateful-button>
|
||||
<app-stateful-button size="large" w-id="button2">button2</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize ref="button1">${data.buttonSize}</app-stateful-button>
|
||||
<app-stateful-button size="large" ref="button2">button2</app-stateful-button>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
<app-stateful-button size=data.buttonSize w-id="button1">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize w-id="button2">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize ref="button1">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize ref="button2">${data.buttonLabel}</app-stateful-button>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
<app-stateful-button size=data.buttonSize w-id="button1">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize w-id="button2">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize ref="button1">${data.buttonLabel}</app-stateful-button>
|
||||
<app-stateful-button size=data.buttonSize ref="button2">${data.buttonLabel}</app-stateful-button>
|
||||
</div>
|
||||
@ -1,7 +1,7 @@
|
||||
<div w-bind>
|
||||
<div w-onclick="handleDivClick">
|
||||
Hello
|
||||
<button w-id="button" type="button" w-onclick="handleButtonClick">
|
||||
<button ref="button" type="button" w-onclick="handleButtonClick">
|
||||
Button
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div w-bind="./widget">
|
||||
[app-async] ${data.name}
|
||||
|
||||
<app-hello name="Async" w-id="hello"/>
|
||||
<app-hello name="Async" ref="hello"/>
|
||||
</div>
|
||||
@ -1,7 +1,7 @@
|
||||
<div w-bind="./widget">
|
||||
<app-hello name="Frank" w-id="helloFrank"/>
|
||||
<app-async name="async1" w-id="async1"/>
|
||||
<app-hello name="John" w-id="helloJohn"/>
|
||||
<app-async name="async2" w-id="async2"/>
|
||||
<app-hello name="Jane" w-id="helloJane"/>
|
||||
<app-hello name="Frank" ref="helloFrank"/>
|
||||
<app-async name="async1" ref="async1"/>
|
||||
<app-hello name="John" ref="helloJohn"/>
|
||||
<app-async name="async2" ref="async2"/>
|
||||
<app-hello name="Jane" ref="helloJane"/>
|
||||
</div>
|
||||
@ -1,2 +1,2 @@
|
||||
div w-bind
|
||||
button w-id="button" w-onMouseMove='handleButtonMouseMove' w-onClick="handleButtonClick"
|
||||
button ref="button" w-onMouseMove='handleButtonMouseMove' w-onClick="handleButtonClick"
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
<div id="appFixedId" class="app-fixed-id" w-bind="./widget">
|
||||
<h1>app-fixed-id</h1>
|
||||
<div w-id="wrapper">
|
||||
<app-hello w-id="hello" name="hello"/>
|
||||
<div ref="wrapper">
|
||||
<app-hello ref="hello" name="hello"/>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,4 +1,4 @@
|
||||
<div w-bind>
|
||||
Hello ${data.name}! You have ${data.messageCount} new messages.
|
||||
<div w-id="foo">foo</div>
|
||||
<div ref="foo">foo</div>
|
||||
</div>
|
||||
@ -1,2 +1,2 @@
|
||||
<div w-bind w-id="foo">
|
||||
<div w-bind ref="foo">
|
||||
</div>
|
||||
@ -1,2 +1,2 @@
|
||||
<div w-bind w-id="foo">
|
||||
<div w-bind ref="foo">
|
||||
</div>
|
||||
@ -3,5 +3,5 @@ var expect = require('chai').expect;
|
||||
module.exports = function(helpers) {
|
||||
expect(function() {
|
||||
require('./template.marko');
|
||||
}).to.throw(/The "w-id" attribute cannot be used in conjuntion with the "w-bind" attribute/);
|
||||
};
|
||||
}).to.throw(/The "ref" attribute cannot be used in conjunction with the "w-bind" attribute./);
|
||||
};
|
||||
|
||||
@ -27,6 +27,7 @@ module.exports = function assignWidgetId(isRepeated) {
|
||||
var context = this.context;
|
||||
var builder = this.builder;
|
||||
|
||||
let widgetRef;
|
||||
var nestedIdExpression;
|
||||
var idExpression;
|
||||
|
||||
@ -52,29 +53,43 @@ module.exports = function assignWidgetId(isRepeated) {
|
||||
// We need to handle the following scenarios:
|
||||
//
|
||||
// 1) The HTML element already has an "id" attribute
|
||||
// 2) The HTML element has a "w-id" attribute (we already converted this
|
||||
// 2) The HTML element has a "ref" or "w-id" attribute (we already converted this
|
||||
// to an "id" attribute above)
|
||||
// 3) The HTML does not have an "id" or "w-el-id" attribute. We must add
|
||||
// 3) The HTML does not have an "id" or "ref" attribute. We must add
|
||||
// an "id" attribute with a unique ID.
|
||||
|
||||
var isCustomTag = el.type !== 'HtmlElement';
|
||||
|
||||
if (el.hasAttribute('ref')) {
|
||||
widgetRef = el.getAttributeValue('ref');
|
||||
|
||||
el.removeAttribute('ref');
|
||||
}
|
||||
|
||||
if (el.hasAttribute('w-id')) {
|
||||
let widgetId = el.getAttributeValue('w-id');
|
||||
console.warn('The "w-id" attribute is deprecated. Please use "ref" instead.');
|
||||
|
||||
if (widgetRef) {
|
||||
this.addError('The "w-id attribute cannot be used in conjuction with the "ref" attribute.');
|
||||
return;
|
||||
}
|
||||
|
||||
widgetRef = el.getAttributeValue('w-id');
|
||||
|
||||
el.removeAttribute('w-id');
|
||||
}
|
||||
|
||||
idExpression = this.buildWidgetElIdFunctionCall(widgetId);
|
||||
|
||||
nestedIdExpression = widgetId;
|
||||
if (widgetRef) {
|
||||
idExpression = this.buildWidgetElIdFunctionCall(widgetRef);
|
||||
|
||||
nestedIdExpression = widgetRef;
|
||||
|
||||
if (isCustomTag) {
|
||||
// The element is a custom tag
|
||||
this.getWidgetArgs().setId(nestedIdExpression);
|
||||
} else {
|
||||
if (el.hasAttribute('id')) {
|
||||
this.addError('The "w-id" attribute cannot be used in conjuction with the "id" attribute');
|
||||
this.addError('The "ref" and "w-id" attributes cannot be used in conjuction with the "id" attribute.');
|
||||
return;
|
||||
}
|
||||
el.setAttributeValue('id', idExpression);
|
||||
@ -140,7 +155,6 @@ module.exports = function assignWidgetId(isRepeated) {
|
||||
if (isCustomTag) {
|
||||
transformHelper.getWidgetArgs().setId(nestedIdExpression);
|
||||
} else {
|
||||
|
||||
el.setAttributeValue('id', idExpression);
|
||||
}
|
||||
|
||||
@ -149,4 +163,4 @@ module.exports = function assignWidgetId(isRepeated) {
|
||||
};
|
||||
|
||||
return this.widgetIdInfo;
|
||||
};
|
||||
};
|
||||
|
||||
@ -16,21 +16,33 @@
|
||||
|
||||
module.exports = function handleWidgetFor() {
|
||||
var el = this.el;
|
||||
var widgetFor;
|
||||
if (el.hasAttribute('for-ref')) {
|
||||
widgetFor = el.getAttributeValue('for-ref');
|
||||
el.removeAttribute('for-ref');
|
||||
}
|
||||
|
||||
var widgetFor = el.getAttributeValue('w-for');
|
||||
|
||||
el.removeAttribute('w-for');
|
||||
if (el.hasAttribute('w-for')) {
|
||||
console.warn('The "w-for" tag is deprecated. Please use "for-ref" instead.');
|
||||
if (widgetFor) {
|
||||
this.addError('The "w-for" tag cannot be used with "for-ref".');
|
||||
return;
|
||||
} else {
|
||||
widgetFor = el.getAttributeValue('w-for');
|
||||
}
|
||||
el.removeAttribute('w-for');
|
||||
}
|
||||
|
||||
if (widgetFor == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the "w-for" attribute
|
||||
// Handle the "for-ref" attribute
|
||||
if (el.hasAttribute('for')) {
|
||||
this.addError('The "w-for" attribute cannot be used in conjuction with the "for" attribute');
|
||||
this.addError('The "for-ref" and "w-for" attribute cannot be used in conjuction with the "for" attribute.');
|
||||
} else {
|
||||
el.setAttributeValue(
|
||||
'for',
|
||||
this.buildWidgetElIdFunctionCall(widgetFor));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -28,6 +28,24 @@
|
||||
"type": "expression",
|
||||
"preserve-name": true
|
||||
},
|
||||
"@for-ref": {
|
||||
"type": "string",
|
||||
"preserve-name": true
|
||||
},
|
||||
"@ref": {
|
||||
"type": "string",
|
||||
"preserve-name": true,
|
||||
"autocomplete": [
|
||||
{
|
||||
"displayText": "ref=\"<method>\"",
|
||||
"snippet": "ref=\"${1:method}\"",
|
||||
"descriptionMoreURL": "http://markojs.com/docs/marko-widgets/get-started/#referencing-nested-widgets"
|
||||
},
|
||||
{
|
||||
"descriptionMoreURL": "http://markojs.com/docs/marko-widgets/get-started/#referencing-nested-widgets"
|
||||
}
|
||||
]
|
||||
},
|
||||
"@w-for": {
|
||||
"type": "string",
|
||||
"preserve-name": true
|
||||
@ -37,7 +55,7 @@
|
||||
"preserve-name": true,
|
||||
"autocomplete": [
|
||||
{
|
||||
"displayText": "w-id=\"<method>\"",
|
||||
"displayText": "w-id=\"<method>\" (Deprecated)",
|
||||
"snippet": "w-id=\"${1:method}\"",
|
||||
"descriptionMoreURL": "http://markojs.com/docs/marko-widgets/get-started/#referencing-nested-widgets"
|
||||
},
|
||||
@ -163,4 +181,4 @@
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,9 @@ module.exports = function transform(el, context) {
|
||||
|
||||
if (el.hasAttribute('w-bind')) {
|
||||
el.setFlag('hasWidgetBind');
|
||||
if (el.hasAttribute('ref')) {
|
||||
transformHelper.addError('The "ref" attribute cannot be used in conjunction with the "w-bind" attribute.');
|
||||
}
|
||||
if (el.hasAttribute('w-id')) {
|
||||
transformHelper.addError('The "w-id" attribute cannot be used in conjuntion with the "w-bind" attribute.');
|
||||
}
|
||||
@ -57,11 +60,11 @@ module.exports = function transform(el, context) {
|
||||
transformHelper.handleWidgetPreserve();
|
||||
}
|
||||
|
||||
if (el.hasAttribute('w-id')) {
|
||||
if (el.hasAttribute('ref') || el.hasAttribute('w-id')) {
|
||||
transformHelper.assignWidgetId();
|
||||
}
|
||||
|
||||
if (el.hasAttribute('w-for')) {
|
||||
if (el.hasAttribute('for-ref') || el.hasAttribute('w-for')) {
|
||||
transformHelper.handleWidgetFor();
|
||||
}
|
||||
|
||||
@ -85,4 +88,4 @@ module.exports = function transform(el, context) {
|
||||
if (el.type !== 'HtmlElement') { // Only custom tags can have nested widgets
|
||||
transformHelper.getWidgetArgs().compile(transformHelper);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user