Skip to content
No description, website, or topics provided.
JavaScript TypeScript HTML
Branch: master
Clone or download
pzuraq Merge pull request #2 from tomdale/patch-1
Add missing closing backtick to README
Latest commit b7e2003 Oct 5, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
addon [REFACTOR] Update to improved API, add TS Oct 4, 2019
app/helpers [REFACTOR] Update to improved API, add TS Oct 4, 2019
config [REFACTOR] Update to improved API, add TS Oct 4, 2019
lib [REFACTOR] Update to improved API, add TS Oct 4, 2019
tests [REFACTOR] Update to improved API, add TS Oct 4, 2019
types [REFACTOR] Update to improved API, add TS Oct 4, 2019
vendor Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.editorconfig Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.ember-cli Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.eslintignore Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.eslintrc.js initial implementation Sep 17, 2019
.gitignore Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.npmignore Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.template-lintrc.js Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
.travis.yml [REFACTOR] Update to improved API, add TS Oct 4, 2019
.watchmanconfig Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
CONTRIBUTING.md Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
LICENSE.md Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
README.md Add missing closing backtick to README Oct 5, 2019
ember-cli-build.js Initial Commit from Ember CLI v3.10.1 Sep 15, 2019
index.js initial implementation Sep 17, 2019
package.json bump version Oct 4, 2019
testem.js
tsconfig.json [REFACTOR] Update to improved API, add TS Oct 4, 2019
yarn.lock [REFACTOR] Update to improved API, add TS Oct 4, 2019

README.md

ember-box

An experimental helper for better 2-way-binding:

<Input @value={{box this.value}} />

Implementing Input:

<input
  value={{unwrap @value}}
  {{on "input" this.onInput}}
>
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);
    }
  }
}

Compatibility

  • Ember.js v2.18 or above
  • Ember CLI v2.13 or above
  • Node.js v8 or above

Installation

ember install ember-box

Usage

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:

{{box this.myValue}}

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;
}
{{#let (box this.value) as |value|}}
  <!-- This will output 123  -->
  {{unwrap value}}

  <!-- This will update the value to 456 when clicked -->
  <button {{on "click" (update value 456)}}>
    Update
  </button>
{{/let}}

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:

<!-- this.value will update when the component updates it internally -->
<Input @value={{box this.value}} />

<!-- this.value will not update, but the component can still read its value -->
<Input @value={{this.value}} />

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');
{{box this "myValue"}}

Wrapping Boxes

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}}:

<Input @value={{wrap (box this.value) this.doSomething}} />
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:

<!-- this.value won't update, but `this.doSomething` will fire when it would have -->
<Input @value={{wrap this.value this.doSomething}} />

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

You can’t perform that action at this time.