ember-ref-bucket v5.0.8
ember-ref-bucket
This addon was created as a rethinking of ember-ref-modifier, with a more simplified API and without some of the downsides of the previous implementation.
The addon allows users to get access to DOM nodes inside components, including accessing wrapping/destroying logic.
A simple use case:
- applying
refmodifier with passed name to an element.
<div {{create-ref "FavouriteNode"}}>hello</div>- gain access to it inside the component class as a decorated property
import Component from '@glimmer/component';
import { ref } from 'ember-ref-bucket';
export default class MyComponent extends Component {
@ref("FavouriteNode") node;
// this.node === "<div>hello</div>"
}API differences, comparing to ember-ref-modifier:
In ember-ref-modifier ref modifier accept 2 positional arguments {{ref this "property"}}:
1. context to set path (this)
2. path to set on context ("property")
In ember-ref-bucket ref modifier accept 1 positional argument {{create-ref "field"}}:
1. reference name ("field")
reference name should be passed as an argument to the @ref("field") decorator, to allow it to find the reference by name.
Compatibility
- Ember.js v3.24 or above
- Ember CLI v3.24 or above
- Node.js v14 or above
Installation
ember install ember-ref-bucketUsage
Examples
Simple player
<audio {{create-ref "player"}} src="music.mp3"></audio>
<button {{on "click" this.onPlay}}>Play</button>import Component from '@glimmer/component';
import { ref } from 'ember-ref-bucket';
import { action } from '@ember/object';
export class Player extends Component {
@ref('player') audioNode;
@action onPlay() {
this.audioNode.play()
}
}Link div to node property.
<div {{create-ref "field"}} ></div>import Component from '@glimmer/component';
import { ref } from 'ember-ref-bucket';
export default class MyComponent extends Component {
@ref("field") node = null;
}Dynamically show div content updates
<div {{create-tracked-ref "field"}}>hello</div>
{{get (tracked-ref-to "field") "textContent"}}Use div as component argument
<div {{create-ref "field"}}>hello</div>
<SecondComponent @helloNode={{ref-to "field"}} />Use registerNodeDestructor
This method is very useful if you want to wrap the node and control its lifecycle.
<div {{create-ref "field"}}>import Component from '@glimmer/component';
import { ref, registerNodeDestructor } from 'ember-ref-bucket';
class NodeWrapper {
constructor(node) {
this.node = node;
}
destroy() {
this.node = null;
}
value() {
return this.node.textContent;
}
}
export default class WrappedNodeComponent extends Component {
@ref('field', (node) => {
const instance = new NodeWrapper(node);
registerNodeDestructor(node, () => instance.destroy());
return instance;
}) node = null;
get value() {
return this.node?.value();
}
}Available decorators:
import { ref, globalRef, trackedRef, trackedGlobalRef } from 'ember-ref-bucket';
/*
ref - usage: @ref('foo', nodeWrapFn?), ref to bucket with current component context
globalRef - usage: @globalRef('foo', nodeWrapFn?), ref to global context (app)
trackedRef - usage: @trackedRef('foo', nodeWrapFn?), tracked ref to local context
trackedGlobalRef - usage: @trackedGlobalRef('foo', nodeWrapFn?), tracked ref to global context (app)
*/Available methods:
import { registerNodeDestructor, unregisterNodeDestructor } from 'ember-ref-bucket';
/*
registerNodeDestructor(node, fn) - to assign any ref-node destructor
unregisterNodeDestructor(node, fn) - to remove assigned ref-node destructor
usage will be like:
@ref('field', (node) => {
const item = new InputMask(node);
registerNodeDestructor(node, () => item.destroy());
return item;
});
*//*
nodeFor - functional low-level primitive to get node access
*/
import { nodeFor } from 'ember-ref-bucket';
const domNode = nodeFor(this, 'field');Definition of @trackedRef decorators
If you use dom node in
@trackedchain calculations, you should usetrackedRef.If you don't need to rerun the tracked chain (for example, you use
refonly for some event-based dom access), you should not usetrackedRef.
Definition of {{create-tracked-ref}} modifiers
- If you need to watch for node changes (resize, content, attributes), you can use the
create-tracked-refmodifier. It can add observe resizing and mutations for the associated element and will mark it as "dirty" for any mutation.
Options:
resize- default:false, if truthy observes the resizing of the DOM element.attributes- default:false, if truthy observes the changing of any attribute on the DOM element.character- default:false, if truthy observes the change of the innerText of the DOM element. Note that setting innerText can change the children or the character depending on the current content of the element.children- default:false, if truthy observes changes to the list of direct children of the DOM element.subtree- default:false, if truthy observes the above options on the entire DOM subtree, not just the element decorated by the modifier.
Definition of {{tracked-ref-to}} helpers
- If you need to recalculate helper if some dom node changes (size, children, attributes), you need to use
tracked-ref-tohelper. - If you don't need it (you need to just have ref to dom node), you should choose
ref-tohelper.
Template-only components
create-refmodifier andref-tohelpers will not work in template-only components (because of no context). You should usecreate-global-refandglobal-ref-toinstead. You can also provide abucketparam to thecreate-refmodifier / helper.
The addon provide only 1 modifier (create-ref) and 1 helper (ref-to). Other derivatives will be transformed, and are described below:
Modifiers will be transformed according to this table:
| Invocation | Will be transformed to |
|---|---|
{{create-ref "foo"}} | {{create-ref "foo" bucket=this}} |
{{create-tracked-ref "foo"}} | {{create-ref "foo" bucket=this tracked=true}} |
{{create-global-ref "foo"}} | {{create-ref "foo" bucket=undefined}} |
{{create-tracked-global-ref "foo"}} | {{create-ref "foo" bucket=undefined tracked=true}} |
Helpers will be transformed according to this table:
| Invocation | Will be transformed to |
|---|---|
{{ref-to "foo"}} | {{ref-to "foo" bucket=this}} |
{{tracked-ref-to "foo"}} | {{ref-to "foo" bucket=this tracked=true}} |
{{global-ref-to "foo"}} | {{ref-to "foo" bucket=undefined}} |
{{tracked-global-ref-to "foo"}} | {{ref-to "foo" bucket=undefined tracked=true}} |
Contributing
See the Contributing guide for details.
Version matrix:
Ember-Modifier 4 - v5; Ember 3.28 - v4; Ember 3.24 - v3
License
This project is licensed under the MIT License.
8 months ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago