UNPKG

flood-simple-form

Version:

The Data Down, Actions Up form builder with ember-changeset and validations

117 lines (100 loc) 3.29 kB
import Ember from 'ember'; import computed from 'ember-computed'; const { observer, run, get, Mixin, guidFor, isPresent } = Ember; /** * Merges 1 or more changesets together returning a fresh changeset * containing the changes and errors of all combined changesets. * * @param {Changeset...} changesets * @public * @return {Changeset} */ export function compositeChangeset(...changesets) { let masterChangeset = changesets.shift(); changesets.forEach((changeset) => masterChangeset = masterChangeset.merge(changeset)); return masterChangeset; } export const SECTIONS = '_sections'; export const CHANGE_ACTION = '_change'; export const REMOVE_ACTION = '_remove'; export default Mixin.create({ [SECTIONS]: null, title: null, init() { this[SECTIONS] = new Map(); this._super(); }, changesetDidChange: observer('changeset.change', 'changeset.error', 'changeset', function() { // console.debug('changesetDidChange'); let changeset = get(this, 'changeset'); if (changeset.get('isDirty')) { this.send('_sendUpdate'); } }), compositeChangeset: computed('changeset.change', 'changeset.error', 'changeset', SECTIONS, { get() { let masterChangeset = get(this, 'changeset'); if (!isPresent(masterChangeset)) { return null; } return compositeChangeset(masterChangeset, ...this[SECTIONS].values()); } }), changesetId: computed('changeset', { get() { return guidFor(get(this, 'changeset')); } }), change: computed.alias('compositeChangeset.change'), changes: computed.alias('compositeChangeset.changes'), error: computed.alias('compositeChangeset.error'), errors: computed.alias('compositeChangeset.errors'), actions: { /** * Handles changes from form inputs by field name and value, assigning the * result directly to this section's changeset. * * NOTE: There's no need to trigger an update here as we do so in the observer. * * @private */ inputValueChanged(field, value) { let sectionChangeset = get(this, 'changeset'); sectionChangeset.set(field, value); this.propertyDidChange('changeset'); this.send('_sendUpdate'); }, /** * Handles changes from nested changesets, merging them with our own changeset, * then propagating the composite changeset to the parent section/form. * * @private */ mergeSubChangeset({ id, changeset }) { let sections = get(this, SECTIONS); sections.set(id, changeset); this.propertyDidChange(SECTIONS); this.send('_sendUpdate'); }, removeSubChangeset({ id }) { let sections = get(this, SECTIONS); if (sections.has(id)) { sections.get(id).rollback(); sections.delete(id); this.propertyDidChange(SECTIONS); this.send('_sendUpdate'); } }, _sendUpdate() { run.scheduleOnce('actions', this, function() { let changeset = this.get('changeset'); if (!changeset) { return; } let compositeChangeset = this.get('compositeChangeset'); let changesetId = get(this, 'changesetId'); this.sendAction(CHANGE_ACTION, { id: changesetId, changeset: compositeChangeset }); }); } } });