An experimental helper for better 2-way-binding:
Implementing Input
:
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { update } from 'ember-box';
export default class Input extends Component {
@action
onInput({ target: { value } }) {
update(this.args.value, value);
if (this.args.onInput) {
this.args.onInput(value);
}
}
}
- Ember.js v2.18 or above
- Ember CLI v2.13 or above
- Node.js v8 or above
ember install ember-box
ember-box
provides the following helpers:
{{box}}
{{wrap}}
{{unwrap}}
{{update}}
And their corresponding functions:
import {
box,
wrap,
unwrap,
update
} from 'ember-box';
The main helper is the box
helper, which receives a path and returns a Box,
which is a reference to that value:
This box can be passed around, and the value it references can be accessed or updated wherever it goes:
import Component from '@glimmer/component';
export default class MyComponent extends Component {
this.value = 123;
}
You can also unwrap or update a value in JavaScript:
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { unwrap, update } from 'ember-box';
export default class MyOtherComponent extends Component {
get boxValue() {
return unwrap(this.args.box);
}
@action
updateBox(newValue) {
update(this.args.box, newValue);
}
}
Note: The
update
function updates the box immediately, but the{{update}}
helper returns a callback that can be used to update the value later. This is because that is what is normally needed in a template.
unwrap
and update
can also both receive plain JS values. unwrap
will
return the value, and update
will no-op. This allows you to write components
that can optionally receive Boxes:
You can also create Boxes in js
by providing a context and path, or by
providing a context and path directly to the helper:
box(this, 'myValue');
Sometimes, you may want to intercept an update to a Box, either to do some other
action when the value changes (a side-effect) or to process the value. You can
wrap boxes to do this with wrap
and {{wrap}}
:
export default class MyComponent extends Component {
@action
doSomething(newValue, _super) {
// do things
_super(newValue);
}
}
The wrapper callback receives the new value, and the super setter, which should
be called if you want to set the value on the box. wrap
can be used to wrap
boxes repeatedly, and unwrap
will recursively unwrap all of them. Also, like
with unwrap
and update
, wrap
can be used with non-Box values to observe
their attempted changes:
See the Contributing guide for details.
This project is licensed under the MIT License.