Можно попробовать сделать через слоты:
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<title>Angular Test</title>
</head>
<body ng-controller="BodyCtrl as vm">
<div test-widget>
<test-widget-title>Hello!</test-widget-title>
<test-widget-body>Widget 1</test-widget-body>
</div>
<div test-widget>
<test-widget-body>Widget 2</test-widget-body>
</div>
<script src="https://unpkg.com/angular@1.6.4/angular.js"></script>
<script type="text/javascript">
angular
.module('app', [])
.controller('BodyCtrl', function() {})
.directive('testWidget', function() {
return {
restrict: 'A',
scope: {},
transclude: {
'title': '?testWidgetTitle',
'body': 'testWidgetBody'
},
template: '' +
'<div>BEGIN</div>' +
'<div ng-if="vm.hasTitle">' +
' TITLE: <b ng-transclude="title"></b>' +
'</div>' +
'<div ng-transclude="body"></div>' +
'<div>END</div>' +
'<p></p>',
controllerAs: 'vm',
controller: function($transclude) {
var vm = this;
vm.hasTitle = $transclude.isSlotFilled('title');
},
link: function(scope, elem, attrs, ctrl, $transclude) {
//var vm = scope.vm = {};
//vm.hasTitle = $transclude.isSlotFilled('title');
}
};
});
</script>
</body>
</html>