Short Question:
How to create a <input type="text"> which contains a custom-format string serialization of an object in a way that editing the string updates the model and vice versa?
I think AngularJS’ directives are the way to go, but i can’t get it pinned down.
Long Question:
Prequel
I have a object which is my application’s “master model”. it can be serialized to a string of a specific format:
-
it has 2-3 attributes, whose serializations are joined by “;” (no trailing “;” if the third is missing)
-
attributes 2 and 3 are lists of objects, and serialized by joining those with “,”.
-
the serialization of the objects is just one of their string attributes, or two ow them with “x” between.
so i have a constructor (accepting a spec string), and a toString function. Following; the latter for clarity:
World.prototype.toString = function() {
var spec = [];
spec[0] = this.version;
spec[1] = this.layers.map(function(layer) {
var c = (layer.c > 1) ? layer.c + 'x' : '';
return c + layer.id; //e.g. 'T' or '2xT'
}).join(',');
//spec[2] in python: ','.join(option.id for option in options if option.checked)
var options = this.options.filter(function(option) {
return option.checked;
});
if (options.length > 0)
spec[2] = options.map(function(option) {
return option.id;
}).join(',');
return spec.join(';');
};
The directive i tried to use looks thusly, but the $watch only fires once.
angular.module('layersApp', []).directive('spec', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch('world', function(val) {
element.val(val.toString());
console.log('object updated', element.val());
}, true);
element.blur(function(e) {
scope.world = new World(element.val());
});
}
};
});
Actual long question
What i want is an easy way to make this work,
<input type="text" data-ng-model="theWorld" spec>
where spec is the custom directive shown above, setting up the two-way binding
Outlook
it would be awesome if this could result in a generic “serialization” directive used like that:
<input type="text" data-serialization="string2Foo, foo2String" data-ng-model="foo">
Which would look up the object foo, and the functions string2Foo and foo2String to setup custom (de)serialization.
I think you can use of
$parsersand$filtersofngModelcontroller.Here is the simplest example of doing it.
http://plnkr.co/edit/13PJN2
It should be easy to add validation, too.
I tried to make it accept custom serializer from parent scope, but failed to do so. Not sure about it.