Thanks. I got it working nicely. I can now create editors using template that are angular aware (2 way binding, ng- event aware, with isolated scope). This should help me write custom editor a lot faster. Here is the final code:
MYAPP.factory ('PopoverEditor', function ($log, $compile, $rootScope) {
var self = Handsontable.editors.BaseEditor.prototype.extend();
self.prototype.init = function() {
$log.debug ('init popover editor');
var template = [
'<div class="panel htPopoverEditor" style="min-width: 150px">',
' <div class="panel-heading">',
' <div class="text-center">{{title}}<a class="pull-right" ng-click="cancel()">x</a></div>',
' </div>',
' <div class="panel-content">',
' <p>Value: <input ng-model="mymodel" class=""></p>',
' </div>',
' <div class="panel-footing">',
' <button class="btn btn-xs btn-danger" ng-click="cancel()">Remove</button>',
' <button class="btn btn-xs btn-primary" ng-click="save()">Save</button>',
' </div>',
'</div>',
].join ('');
// set scope for our editor
var _this = this;
var scope = $rootScope.$new (true);
scope.title = 'Custom Popover';
scope.mymodel = 'whatever you want';
scope.cancel = function () {
$log.debug ('cancel');
_this.cancelChanges();
};
scope.save = function () {
$log.debug ('save');
_this.finishEditing();
};
scope.$on ('$destroy', function () {
$log.debug ('destroying scope of editor');
});
self.content = angular.element ($compile(template) (scope));
self.content.on ('remove', function () {
$log.debug ('removing popover dom');
scope.$destroy();
});
this.popover = self.content[0];
this.popover.style.display = 'none';
this.instance.rootElement.appendChild(this.popover);
};
self.prototype.prepare = function() {
$log.debug ('preparing popover');
// Remember to invoke parent's method
Handsontable.editors.BaseEditor.prototype.prepare.apply(this, arguments);
// Handsontable.Dom.empty(this.popover);
};
self.prototype.getValue = function() {
$log.debug ('get value popover');
return self.content.scope()['mymodel'];
};
self.prototype.setValue = function(value) {
$log.debug ('set value popover:', value);
self.content.scope().$apply(function () {
self.content.scope()['mymodel'] = value;
});
};
self.prototype.focus = function () {
$log.debug ('set focus');
this.getInputElement().focus();
};
self.prototype.getInputElement = function () {
return self.content.find ('input');
};
self.prototype.open = function() {
$log.debug ('open popover');
var width = Handsontable.Dom.outerWidth(this.TD);
// important - group layout reads together for better performance
var height = Handsontable.Dom.outerHeight(this.TD);
var rootOffset = Handsontable.Dom.offset(this.instance.rootElement);
var tdOffset = Handsontable.Dom.offset(this.TD);
var editorSection = this.checkEditorSection();
var cssTransformOffset;
height += Handsontable.Dom.outerHeight(self.content);
switch (editorSection) {
case 'top':
cssTransformOffset = Handsontable.Dom.getCssTransform(this.instance.view.wt.wtScrollbars.vertical.clone.wtTable.holder.parentNode);
break;
case 'left':
cssTransformOffset = Handsontable.Dom.getCssTransform(this.instance.view.wt.wtScrollbars.horizontal.clone.wtTable.holder.parentNode);
break;
case 'corner':
cssTransformOffset = Handsontable.Dom.getCssTransform(this.instance.view.wt.wtScrollbars.corner.clone.wtTable.holder.parentNode);
break;
}
var editorStyle = this.popover.style;
if (cssTransformOffset && cssTransformOffset !== -1) {
editorStyle[cssTransformOffset[0]] = cssTransformOffset[1];
} else {
Handsontable.Dom.resetCssTransform(this.popover);
}
// editorStyle.height = height + 'px';
editorStyle.minWidth = width + 'px';
editorStyle.top = tdOffset.top - rootOffset.top - 1 + 'px';
editorStyle.left = tdOffset.left - rootOffset.left + 'px';
editorStyle.margin = '0px';
editorStyle.display = '';
$log.debug ('set style popover', editorStyle);
};
self.prototype.checkEditorSection = function() {
if (this.row < this.instance.getSettings().fixedRowsTop) {
if (this.col < this.instance.getSettings().fixedColumnsLeft) {
return 'corner';
} else {
return 'top';
}
} else {
if (this.col < this.instance.getSettings().fixedColumnsLeft) {
return 'left';
}
}
};
self.prototype.close = function() {
$log.debug ('close popover');
this.popover.style.display = 'none';
};
Handsontable.editors.registerEditor('popover', self);
return self;
});