I would utilise the fact that the template property can be a function (tElem, tAttrs) { ... } (docs) that returns a string to modify the template based on the attributes present.
The way I would do this is to use jQuery and some custom elements to indicate which parts of the template are conditional.
Here is a quick sample template function:
function template($element, $attrs) {
var fullTemplate = $('<div><if-attr name="a"><div ng-if="$ctrl.a"></div></if-attr></div>');
fullTemplate.find('if-attr').each(function() {
if (attrs.hasOwnProperty($(this).attr('name'))) {
$(this).replaceWith(this.innerHTML);
} else {
$(this).remove();
}
});
return fullTemplate[0].outerHTML;
}
Sample output
template(null, {a: '1'}) => "<div><div ng-if="$ctrl.a"></div></div>"
template(null, {b: '1'}) => "<div></div>"
Known Limitations
This breaks down if you wanted to fetch the template from a URL (and it isn’t prepopulated in the $templateCache) but that doesn’t appear to be your situation.
If Minifying
The documentation states that if template is a function, it is injected with $element and $attrs. That means that if you are minifying your code, make sure you use a minification-safe method of specifying the function parameter names.
e.g.
template: ['$element', '$attrs', function ($elem, $attrs) {
// ...
}],
or
function templateFn($elem, $attrs) {
// ...
}
templateFn['$inject'] = ['$element', '$attrs'];
template: templateFn,