- The
onAfterUpdate
lifecycle event was renamed toonUpdate
- The
init()
constructor for a widget is only called once even if a widget is rerendered - When a nested widget is rerendered, it is no longer reinitialized.
- Everything related to Dust has been removed.
- Integrated 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
- New lifecycle event: 'onRender'
Widget.prototype.render = function(input, out) { ... }
is no longer allowed. UseWidget.prototype.renderer = function(input, out) { ... }
ordefineComponent(...)
instead (recommended).- NOTE:
this.widgets.foo
has been removed sincemarko-widgets@^3
- Simpler syntax for defining widget types:
Old:
function Widget() {
this.doSomething();
}
Widget.prototype = {
doSomething: function() {
}
};
module.exports = Widget;
New:
module.exports = require('marko-widgets').defineWidget({
init: function() {
this.doSomething();
},
doSomething: function() {
}
});
- Ability to define the widget and the renderer in the same JavaScript file:
module.exports = require('marko-widgets').defineComponent({
template: require.resolve('./template.marko'),
getTemplateData: function(state, input) {
return {
hello: 'world'
};
},
init: function() {
this.doSomething();
},
doSomething: function() {
}
});
- Support for stateful widgets (changing widget state causes a widget to be rerendered)
module.exports = require('marko-widgets').defineComponent({
template: require.resolve('./template.marko'),
getInitialState: function(input) {
return {
size: input.size || 'normal'
};
},
getInitialBody: function(input) {
return input.label || input.renderBody;
},
getTemplateData: function(state, input) {
var rootAttrs = {};
var classParts = ['app-button'];
var type = 'button';
var size = state.size;
if (size !== 'normal') {
classParts.push('app-button-' + size);
}
rootAttrs['class'] = classParts.join(' ');
return {
type: type,
rootAttrs: rootAttrs
};
},
setSize: function(size) {
this.setState('size', size);
},
getSize: function() {
return this.state.size;
}
});
With marko-widgets, this.widgets.foo
is no longer support and this.widgets
will be null
. Instead, you should this.getWidget('foo')
.
marko-widgets v2 introduced the potential for a circular dependency. To avoid problems, you should no longer use module.exports
in your widget JavaScript module as shown below:
Old widget.js:
function Widget() {
// ...
}
Widget.prototype = {
// ...
};
module.exports = Widget;
New widget.js:
function Widget() {
}
Widget.prototype = {
};
exports.Widget = Widget;
You should also do the same for your UI component renderer:
Old renderer.js:
module.exports = function render(input, out) {
// ...
}
New renderer.js:
exports.renderer = function(input, out) {
// ...
}
- Fixes #102 Fix how require path to marko-widgets is generated in compiled templates
- Fixes #101 - Widget binding broken when UI component is npm linked in
- Documentation fixes
- Fix for #98 - Properly preserve widget stack when beginning async rendering
- Fixes #92 - w-preserve* does not work on widget root node
- Integrated morphdom to more efficiently transform the existing DOM instead of replacing it entirely
- Significant performance improvements
- Code cleanup
- Breaking changes:
- The
onAfterUpdate
lifecycle event was renamed toonUpdate
- Reusing DOM nodes might change application behavior (in rare cases)
- The
init()
constructor for a widget is only called once even if a widget is rerendered
- The
- Dust-related code has been removed
- New lifecycle event: 'onRender'
- Fixed #41 - Initialize widgets in nested batched updates first
- Fixed #54 - Allow event handler method name to be dynamic
- Internal code improvements
- Fixed #49 - Allow
w-id
to be used in an intermediate template
- Fixed #48 - Improved logic for generating repeated widget IDs to handle gaps
- Fixed #47 - Switched from
optimizer
to lasso for tests - Fixed #46 - Allow
w-id
attr with<invoke>
- Added support
w-preserve-if
andw-preserve-body-if
. These new attributes allow DOM elements to be conditionally preserved. The right-hand side of the attribute should a JavaScript expression. If the expression evaluates tofalse
then the elements will not be preserved. Example usage:
<div w-bind>
<!-- Don't rerender the search results if no search results are provided -->
<app-search-results items="data.searchResults"
w-preserve-if="data.searchResults == null"/>
</div>
- Stateful widgets
- Batched updates to the DOM
- New methods exported by marko-widgets:
defineComponent(def)
defineWidget(def)
defineRenderer(def)
- New custom taglib attributes:
w-preserve
,w-preserve-body
andw-body
- New Widget methods:
setState(name, value)
setState(newState)
replaceState(newState)
setProps(newProps)
setStateDirty(name)
onBeforeDestroy()
onDestroy()
onBeforeUpdate()
onAfterUpdate()
- New rendering properties:
template
(String
path to a Marko template)getInitialProps(input)
getInitialState(input)
getTemplateData(state, input)
getWidgetConfig(input)
getInitialBody(input)
- General code cleanup and performance improvements
- ❗ Removed support for
Widget.prototype.render = function(input, out) { ... }
- ❗ Removed support for
this.widgets.foo
(usethis.getWidget('foo')
instead) - Added support for repeated DOM elements and repeated widgets:
<div class="my-component" w-bind="./widget">
<ul>
<li w-id="todoListeItems[]" for="todoItem in data.todoItems">
<app-todo-item w-id="todoItems[]" todo-item="todoItem"/>
</li>
</ul>
</div>
var todoListeItems = this.getEls('todoListeItems');
var todoItemWidgets = this.getWidgets('todoItems');
- Added new methods:
getEls(id)
getWidgets(id)
- Deprecate
w-el-id
in favor ofw-id
- Internal code cleanup
- Fixed #19 - Allow
w-on
for custom widget events
- Fixed #18 - Widgets in async blocks now initialize in the correct order
- Fixed #17 - Allow
w-config
withw-extend
- Internal: use 'renderBody(out)' instead of
invokeBody()
- Introduced
require('marko-widgets').render(renderer, input)
- Replaced
require('marko-widgets').renderFunc(renderer)
withrequire('marko-widgets').renderable(exports, renderer)
- Improved documentation
- Added support for using
exports.extendWidget = function(widget, widgetConfig) { ... }
- Allow
w-extend
attribute to be empty
- Allow empty value for
w-bind
(e.g.<div w-bind>...</div>
) and default to./widget
or./
- Export new method for creating a client-side render function:
function renderer(input, out) {
out.write('Hello ' + input.name + '!');
}
exports.render = require('marko-widgets').renderFunc(renderer);
- Added new sub-module,
require('marko-widgets/dom')
, that exports raptor-dom
Example:
require('marko-widgets/dom').removeChildren(document.body);
- Added new sub-module,
require('marko-widgets/renderer')
, that exports raptor-renderer
Example:
require('marko-widgets/renderer').renderFunc(renderer);
- Improved mechanism for registering and loading widget types.
- Use
exports.Widget
instead ofmodule.exports = Widget
- Fixes #14 - Making adding event listeners more robust by allowing initialization even if document is not ready
- Changes to prevent unoptimized code in V8
- Fixes #11 Added support for w-on* attributes. Other cleanup and tests