ember-validated-form-buffer
ember-validated-form-buffer copied to clipboard
A validated form buffer that wraps Ember Data models for use in forms.
ember-validated-form-buffer
ember-validated-form-buffer implements a validating buffer that wraps Ember
Data models and can be used in forms to buffer user inputs before applying them
to the underlying model. The buffer also handles mixing client side
validation errors and errors returned from the API as well as functionality
that detects which API errors may have become obsolete due to modifications to
the respective properties.
ember-validated-form-buffer helps implementing common forms functionality:
- preventing modification of models until the form is submitted
- implementing cancel/reset functionality
- filtering irrelevant errors
It leverages ember-buffered-proxy for the buffering functionality and ember-cp-validations for client side validations.
Installation
Install ember-validated-form-buffer with
ember install ember-validated-form-buffer
Example
In order to define a validated form buffer on a controller or component, import
the formBufferProperty helper and define a property that wraps the model
instance. Pass in the validations mixin as returned by ember-cp-validations.
When the form is submitted, apply the buffered changes and save the model or
discard them to reset all user input:
import Ember from 'ember';
import { validator, buildValidations } from 'ember-cp-validations';
import formBufferProperty from 'ember-validated-form-buffer';
const Validations = buildValidations({
name: validator('presence', true)
});
export default Ember.Controller.extend({
data: formBufferProperty('model', Validations),
actions: {
submit(e) {
e.preventDefault();
this.get('data').applyBufferedChanges();
this.get('model').save();
},
reset() {
this.get('data').discardBufferedChanges();
}
}
});
Then instead of binding form inputs to model properties directly, bind them to the buffer instead:
<form onsubmit={{action 'submit'}}>
<label>Name</label>
{{input value=data.name}}
<button type="submit">Save</button>
<button type="button" onclick={{action 'reset'}}>Reset</button>
</form>
If you're not using 2 way data bindings for the input but Data Down/Actions Up, make sure to update the buffer property instead of the model's when the respective action is called:
<form onsubmit={{action 'submit'}}>
<label>Name</label>
<input value="{{data.name}}" onkeydown={{action (mut data.name) value='currentTarget.value'}}/>
<button type="submit">Save</button>
<button type="button" onclick={{action 'reset'}}>Reset</button>
</form>
API
The buffer
The buffer has methods for applying and discarding changes as well as properties for accessing its current error state.
-
applyBufferedChangesapplies the changes in the buffer to the underlying model. -
discardBufferedChangesdiscards the buffered changes to that the buffer's state is reset to that of the underlying model. -
apiErrorsreturns the errors as returned by the API when the model was last submitted. -
clientErrorsreturns the client side validation errors as returned by ember-cp-validations. -
displayErrorsreturns both the API errors as well as the client side validation errors. This does not include any API errors on properties that have been changed after the model was submitted as changing a property that was previously rejected by the API potentially renders the respective error invalid. -
hasDisplayErrorsreturns whether the buffer currently has any errors to display which is the case whendisplayErrorsis not empty.
For further info on the buffer's API, check the docs of ember-buffered-proxy and ember-cp-validations respectively.
The buffer can be imported and used directly:
import { Buffer } from 'ember-validated-form-buffer';
const Validations = buildValidations({
name: validator('presence', true)
});
export default Ember.Controller.extend({
data: computed('model', function() {
let owner = Ember.getOwner(this);
return Buffer.extend(Validations).create(owner.ownerInjection(), {
content: this.get('model')
});
}),
…
It is generally easier to use the formBufferProperty macro to define a form
buffer property though:
The formBufferProperty helper
The formBufferProperty macro takes the name of another property that returns
the Ember Data model to wrap in the buffer as well as a list of mixins that
will be applied to the buffer. These mixins usually include the validation
mixin as created by ember-cp-validations's buildValidations method.
If any of the provided mixins define an unsetApiErrors method, that method
will be called whenever any property is changed on the buffer. The method
returns a property name or an array of property names for which all API errors
will be excluded from the displayErrors until the model is submitted to the
API again. That way it's possible to hide API errors on a property when a
related property changes:
import formBufferProperty from 'ember-validated-form-buffer';
const Validations = buildValidations({
name: validator('presence', true)
});
export default Ember.Controller.extend({
data: formBufferProperty('model', Validations, {
unsetApiErrors() {
let changedKeys = Ember.A(Object.keys(this.get('buffer')));
if (changedKeys.includes('date') || changedKeys.includes('time')) {
return 'datetime'; // whenever the "date" or "time" attributes change, also hide errors on the virtual "datetime" property
}
}
})
…
License
ember-validated-form-buffer is developed by and ©
simplabs GmbH and contributors. It is released under the
MIT License.
ember-validated-form-buffer is not an official part of
Ember.js and is not maintained by the Ember.js Core Team.