Reputation: 4718
Situation: I'm porting over, or should I say attempting to port Lakshan Perera's Simple jQuery ColorPicker (https://github.com/laktek/really-simple-color-picker) over to Angular. After reviewing similar problems on SO it seems like some folks assign the scope of the plugin through the controller, but the proper (Angular) way to do this is by wrapping the plug-in in a directive. I'm getting close. I'm able to properly render the plug-in in my view via my new custom attribute, but I'm not sure how to set up the directive to pass the input value to attribute's value (an ng-model). The actual input updates, but the Angular isn't listening for a change and so is in effect unaware that the input value has been updated. The official documentation talks about setting up custom attributes here (http://docs.angularjs.org/guide/directive), but I still was unable to figure out how to I actually watch a change in the element and then push that value to the attribute's value.
Desired functionality -
<input my-widget="{{color}}" type="text"/> <!-- my-widget instantiates my directive -->
<h1 style="color:{{color}}"></h1> <!-- I would like the input value to dump into the attribute's value, in this case {{color}} -->
Here is what I have so far:
app.directive('myWidget', function(){
var myLink = function(scope, element, attr) {
scope.$watch('element',function(){
var value = element.val();
element.change(function(){
console.log(attr.ngModel); // This is currently logging undefined
// Push value to attr here?
console.log( value + ' was selected');
});
});
var element = $(element).colorPicker();
}
return {
restrict:'A',
link: myLink
}
});
Question: How the heck do I set up the attribute value to catch the element's updated value?
Upvotes: 4
Views: 3656
Reputation: 159125
I would implement it like this:
app.directive('colorPicker', function() {
return {
scope: {
color: '=colorPicker'
},
link: function(scope, element, attrs) {
element.colorPicker({
// initialize the color to the color on the scope
pickerDefault: scope.color,
// update the scope whenever we pick a new color
onColorChange: function(id, newValue) {
scope.$apply(function() {
scope.color = newValue;
});
}
});
// update the color picker whenever the value on the scope changes
scope.$watch('color', function(value) {
element.val(value);
element.change();
});
}
}
});
You'd use it like so:
<input color-picker="color">
Here is a working jsFiddle, with a few little widgets to toy with: http://jsfiddle.net/BinaryMuse/x2uwQ/
The jsFiddle uses an isolate scope to bind a scope value color
to whatever was passed in to the color-picker
attribute. We $watch
the expression 'color'
to see when this value changes, and update the color picker appropriately.
Upvotes: 6