draftable-entity

Draftable entity: edit -> save or reset -> get model|diff|draft

Usage no npm install needed!

<script type="module">
  import draftableEntity from 'https://cdn.skypack.dev/draftable-entity';
</script>

README

Build Status

Draftable entity: edit -> save or reset -> get model|diff|draft

Disclaimer: sandbox isn't an example of flawless code, this is just a sandbox.

  • has places where need move code parts to new components.
  • for :key prop using index of element instead of uniq id of iteratable entity
  • ...

Links

Install

yarn add draftable-entity or npm install draftable-entity

Example

Use yarn sandbox:serve after yarn install for serve example vue project at localhost:8050 and see as it works

Draftable Entity instance

  • getters:
getter ret type description
--- --- ---
entityName string entity.constructor.name
draft IDraftableModel Proxy object with read/write access
model IDraftableModel Proxy object with read access
identityKey DraftableIdentityKey Id of entity
isNew boolean Will be true if identityValue hasn't been null and undefined on create entity
identityPayload DraftableIdentityPayload {{ [identityKey]: identityValue }}
hasIdentityValue boolean Will be true if identityValue haven't be null and undefined
identityValueChanged boolean Will be true if identityValue hasn't be change
modelIdentityValue DraftableIdentityValue identityValue from model
draftIdentityValue DraftableIdentityValue identityValue from draft
hasDraft boolean If draft !== model
isTouched boolean If draft !== model, light check changes, use hasDraft instead of
diff IDraftableModel Same model that model/draft with changed values only
  • methods:
methods args ret type description
--- --- --- ---
saveDraft() --- void Save changes to original model, after model === draft
resetDraft() --- void Reset all changes, after model === draft
getChanges() --- DraftableEntityChanges Returns array with changes
exactModel() --- IDraftableModel Returns original model
exactDraft() --- IDraftableModel Returns draft model
exactDiff() --- IDraftableModel Returns model with changed values only
  • see ./src/types.ts for more info about args and ret types

Discover

*) entity.model and entity.draft is empty Proxy objects:

const model = { someProp: 'someVal' };
const entity = new DraftableEntity(model);

model !== entity.model && model !== entity.draft, but model === entity.model.__source__ && model === entity.draft.__source__ (before edit)

*) (model|draft).__source__ returns original passed (model) and drafted (draft) models, if you really need it, use entity.exactDraft|exactModel methods instead of

*) You can't write smth to entity.(model|draft) directly:

const model = { someProp: 'someVal' };
const entity = new DraftableEntity(model);

entity.draft = { otherDraft: 1 };
entity.model = { otherModel: 1 };

entity.(model|draft) === {}, original model and draft hasn't been changed. Use properties for read/write values:

<!-- some editable component -->
...
<input v-model="entity.draft.propertyName">
...
<!-- some readable component -->
...
<div class="column">{{ entity.model.propertyName }}</div>
...

*) You can't write to entity.model.smthProp = smthValue, entity.model only for read original values.

*) For better (optionality), renew sub arrays/objects with new values:

toggleGender() {
  const { gender } = this.draft;
  this.draft.gender = { gender: !gender.male, male: !gender.male };
}

...

removeFollower({ follower, idx }) {
  const followers = this.draft.followers.slice();
  if (idx) {  
    followers.splice(idx, 1);
    this.draft.followers = followers;
    ...
  }
  ...
}

By entity logic, it will be a little faster. But if you using only exact* methods per custom interval tick (as like RxJS/interval) for getting and detecting changes, do as you want.

*) You can't delete|add property from|to entity.(draft|model)

*) If you need to update current entity model, create entity again with new model. Some example:

const model = { smth: 'value' };
const entity = new DraftableEntity(model);

This entity.isNew === true, because entity.model[DraftableEntity.defaultIdentityKey] === undefined

...
// edit and/or validate entity before post request 
...

const ret = await http.post('smth/api', entity.exactModel())

ret contains same object that entity but with new adds:

{ [DraftableEntity.defaultIdentityKey]: identityValue }

Recreate entity again:

entity = new DraftableEntity(ret);

License

Released under the MIT license