From f4e0e6d1090f5786e2e8b4aa4fd316661cc9f8e7 Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Tue, 29 Jan 2019 09:44:19 -0500 Subject: [PATCH] Begin fleshing out README with info from emberjs/rfcs#415. --- README.md | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 194 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dd96c15..21e42f2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ @ember/render-modifiers ============================================================================== -[Short description of the addon.] +Provides element modifiers that can be used to hook into specific portions of +the rendering lifecycle. Compatibility @@ -19,11 +20,201 @@ ember install @ember/render-modifiers ``` -Usage +Usage Examples ------------------------------------------------------------------------------ -[Longer description of how to use the addon in apps.] +### Example: Scrolling an element to a position +This sets the scroll position of an element, and updates it whenever the scroll +position changes. + +Before: + +```hbs +{{yield}} +``` +```js +export default Component.extend({ + classNames: ['scroll-container'], + + didRender() { + this.element.scrollTop = this.scrollPosition; + } +}); +``` + +After: + +```hbs +
+ {{yield}} +
+``` +```js +export default class Component.extend({ + setScrollPosition(element, scrollPosition) { + element.scrollTop = scrollPosition; + } +}) +``` + +#### Example: Adding a class to an element after render for CSS animations + +This adds a CSS class to an alert element in a conditional whenever it renders +to fade it in, which is a bit of an extra hoop. For CSS transitions to work, we +need to append the element _without_ the class, then add the class after it has +been appended. + +Before: + +```hbs +{{#if shouldShow}} +
+ {{yield}} +
+{{/if}} +``` +```js +export default Component.extend({ + didRender() { + let alert = this.element.querySelector('.alert'); + + if (alert) { + alert.classList.add('fade-in'); + } + } +}); +``` + +After: + +```hbs +{{#if shouldShow}} +
+ {{yield}} +
+{{/if}} +``` +```js +export default Component.extend({ + fadeIn(element) { + element.classList.add('fade-in'); + } +}); +``` + +#### Example: Resizing text area + +One key thing to know about `{{did-update}}` is it will not rerun whenever the +_contents_ or _attributes_ on the element change. For instance, `{{did-update}}` +will _not_ rerun when `@type` changes here: + +```hbs +
+``` + +If `{{did-update}}` should rerun whenever a value changes, the value should be +passed as a parameter to the modifier. For instance, a textarea which wants to +resize itself to fit text whenever the text is modified could be setup like +this: + +```hbs + +``` +```js +export default Component.extend({ + resizeArea(element) { + element.css.height = `${element.scrollHeight}px`; + } +}); +``` + +#### Example: `ember-composability-tools` style rendering + +This is the type of rendering done by libraries like `ember-leaflet`, which use +components to control the _rendering_ of the library, but without any templates +themselves. The underlying library for this is [here](https://github.com/miguelcobain/ember-composability-tools). +This is a simplified example of how you could accomplish this with Glimmer +components and element modifiers. + +Node component: + +```js +// components/node.js +export default Component.extend({ + init() { + super(...arguments); + this.children = new Set(); + + this.parent.registerChild(this); + } + + willDestroy() { + super(...arguments); + + this.parent.unregisterChild(this); + } + + registerChild(child) { + this.children.add(child); + } + + unregisterChild(child) { + this.children.delete(child); + } + + didInsertNode(element) { + // library setup code goes here + + this.children.forEach(c => c.didInsertNode(element)); + } + + willDestroyNode(element) { + // library teardown code goes here + + this.children.forEach(c => c.willDestroyNode(element)); + } +} +``` +```hbs + +{{yield (component "node" parent=this)}} +``` + +Root component: + +```js +// components/root.js +import NodeComponent from './node.js'; + +export default NodeComponent.extend(); +``` +```hbs + +
+ {{yield (component "node" parent=this)}} +
+``` + +Usage: + +```hbs + + + + + +``` License ------------------------------------------------------------------------------