This mixin allows data-binding with statically or dynamicaly created Custom Elements, native HTML Elements, Polymer Elements or all together. Maybe this library should be called "The One Ring"...
To get started
bower install --save Weaverize/dynamic-binding
then import Bindable.js
in your html file:
<script src="bower_components/dynamic-data-binding/Bindable.js"></script>
For custom elements just call a new Binder
on your Custom Element.
class MyElement extends HTMLElement {
constructor() {
super();
this.data = {
name : {
firstname : "John"
}
};
new Binder(this,"data");
//new property can be declared whenever
this.data.name.lastname = "Doe";
}
}
Then in your html you can bind your objects together.
<body>
<my-element id="element"></my-element>
<script>
var element1 = document.getElementById("element");
var element2 = document.createElement("my-element");
document.body.appendChild(element2);
element1._bind("name.firstname", element2);
element1._bind("name.lastname", element2);
</script>
</body>
Check out the example provided in demo/htmlelement that binds with a native html <input>
.
For Polymer Elements, simply apply the mixin to your the element that have to be bound using class extention.
For example:
class MyElement extends Bindable(Polymer.Element) {
//..
}
class MyOtherElement extends Bindable(Polymer.Element) {
//..
}
You can bind properties at run time using like in the following examples:
element._bind("my_prop", otherElement);
element._bind("prop", otherElement, "otherProp");
element._bind("works.also.on.subprop", otherElement, "on.both.sides");
A complete example is available in the demo/polymer it mixes normal Polymer with bindings from this library.
You don't have anything specific to do, just bind the Bindable properties of one with the other.
Check out demo/both for simple demo using elements from the two other demo.
Here is a detailed documentation of the library.
The datastore is where the bindable properties are. Every property found in the datastore are automatically bindable. They don't have to be defined in advance.
For Custom Elements the datastore can have any name. For Polymer we use the Polymer's datastore __data
(with two _
). To expose a Polymer property it should have the flag notify : true
in its definition.
To make an element's properties bindable your have to overload it with this library. This can be done at run time by calling new Binder
on the object you want to bind with. It can also be done in a class declaration either by calling new Binder
in the constructor or using the class mixin (meant mainly for Polymer Elements) which is the second method presented thereafter.
Native elements are overloaded by the contructor of the Binder class.
element
is the element to overload, usuallythis
.datastore
is the name of the datastore corresponding tothis[datastore]
. It should be an object, it will be created if the property is not defined or if it's not an object.
The constructor adds the following methods if needed:
#.get(path)
path
is the dotted string path to the property inside the datastore (without the name of the datastore).
#.set(path, value)
path
is the dotted string path, just like forget
.value
is the value to set, it can be of any type. You can use those utility fonction only if you want, they're not mandatory toget
orset
the binded properties.
Polymer Elements don't have to specify a datastore, __data
will be used automatically using this class mixin.
Polymer Elements already have get
and set
defined natively.
This method creates a two-way binding between two properties of two objects.
path
is the dotted path to the property in first objectobj
is the destination objectdestPath
is the optional dotted path to the destination property.path
would be used if not provided
_bind
returns a function()
that undoes the binding.
The value from the first object will be copied in the second object.
This method creates a one-way binding between two properties of two objects.
path
is the dotted path to the property in first objectobj
is the destination objectdestPath
is the optional dotted path to the destination property.path
would be used if not providedsetter
is an optional fonction to provide a custom way to set the value in the destination object (obj
). It should have the following signaturefunction(value)
.
_bindOneWay
returns a function()
that undoes the binding.
The value from the first object will be copied in the second object.
_bindOneWay
is useful when your binding to a native html element like a <div>
or an <input>
that you want to sync:
this._bindOneWay("name.firstname", div, "innerText");
this._bindOneWay("name.firstname", input, "value");
When you create a bind a function is returned to undo it.
Example:
var unbind = element._bind("prop", otherElement);
unbind();
Changes on both sides will not be propagated to the other after this.
If you make you use _bindOneWay
twice to manually create the two-ways bind that you can unbind one or both as you like.
If your using Polymer and this library to bind sub-properties you should manually bind every step of the path leading to your property.
For example to bind prop.subprop
your should use the following binding:
element._bind("prop",otherElement);
element._bind("prop.subprop",otherElement);
Polymer seems to send an entire object when one of its property is changed.
The current implementation does a recursive crawl through all properties to make them bindable. You have to avoid circular reference (direct or indirect) or an infinite loop will occur.
Avoid this:
prop : {
subprop : {
subsubprop : prop
}
}
Copyright (c) 2018, Weaverize SAS. All rights reserved. Contact: [email protected].