Experimenting with creating a bindable model to make life easier when dealing with complex forms.
Allows:
- Listening for change events anywhere in the model tree
- Change events bubble up the parent tree
- Freeze/unfreeze subtrees (readonly mode)
- Ability to mark nodes with custom metadata (invalid, changed, etc)
- One source of truth - changes are applied synchronously
- Events are async and batched to reduce change notification storms
- Allow two way bindings because we are not babies
Planned:
- Chaining multiple bindables, each with their own validation
- Sync events
Get notified when values change:
import Bindable from 'bindable';
const model = Bindable.from({
person: {
name: 'foo'
}
});
Bindable.observe(model.person.name, () => {
console.log('name is', model.persoin.name.get());
});
model.person.name = 'bar';
// name is barListen for children change events:
import Bindable from 'bindable';
const model = Bindable.from({
person: {
name: 'foo'
}
});
Bindable.observe(model.person, () => {
console.log('name is', model.person.name.get());
});
model.person.name = 'bar';
// name is barMarking nodes with custom metadata:
import Bindable from 'bindable';
const model = Bindable.from({
person: {
name: 'foo'
}
});
Bindable.observe(model.person, () => {
const isValid = model.person.name.get().length > 0;
Bindable.mark(model.person, 'valid', isValid);
console.log('is valid:', Bindable.getMark(model.person, 'valid');
});
model.person.name = '';
// is valid: falseEvents are bundled to minimize notification storms:
import Bindable from 'bindable';
const model = Bindable.from({
name: 'foo'
});
Bindable.observe(model.name, () => {
console.log('name is', model.name.get());
});
model.name = 'bar';
model.name = 'baz';
// name is bazYou can freeze parts of the model:
import Bindable from 'bindable';
const model = Bindable.from({
person: {
name: 'foo'
}
});
Bindable.freeze(model.person);
model.person.name = 'bar';
// throws an Error