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.
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());
});
}
};
});
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
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 $parsers
and $filters
of ngModel
controller.
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.