bigblind
bigblind

Reputation: 12867

How to deal with extra markup used for angular directives?

I have two directives: appButtonGroup and appGroupedButton. My css expects th <app-grouped-button> elements to be direct descendants of <app-button-group>, so they can be laid out as flexbox items. But I want to transclude the appGroupedButton elements into the button group, but that adds an <ng-transclude> element around the grouped buttons.

A way to solve this, would be to make the <ng-transclude> element the flex container, but that would mean that my css 'knows' about the transclude element, which I see as an implementation detail. I've tried using the directive as a comment, but for some reason that doesn't work, and comment directives are being discouraged in the docs.

What's a good way to solve this problem?

Here's the javascript code for the directives:

Navigation.directive('appButtonGroup', function(){
  return {
    restrict: "EA",
    transclude: true,
    controller: function($scope, $location){
      var buttons = $scope.buttons = [];
      console.log("initialized button group controller");

      this.addButton = $scope.addButton = function(button){
        if (buttons.length === 0){
          button.active = true;
        }
        buttons.push(button);
      }

      this.select = $scope.select = function(button){
        angular.forEach(buttons, function(){
          button.active = false;
        });
        button.active = true;
        $location.path(button.hrf);
      }
    },
    template: "<ng-transclude></ng-transclude>"
  }
})
.directive('appGroupedButton', function(){
      return {
        restrict: "EA",
        transclude: true,
        require: '^appButtonGroup',
        scope: {href: '@'},
        link: function(scope, element, attrs, BGCtrl){
          console.log(BGCtrl);
          BGCtrl.addButton(scope);
          console.log("linking button "+scope);
        },
        template: "<div ng-class=active ? \'active\' : \'\''>" +
                  "<ng-transclude></ng-transclude>" +
                  "</div>"
      }
});

And here's my markup for the button group:

<app-button-group>
    <app-grouped-button>Podcasts</app-grouped-button>
    <app-grouped-button>Playlists</app-grouped-button>
    <app-grouped-button>Downloading</app-grouped-button>
    <app-grouped-button>Discover</app-grouped-button>
</app-button-group>

So tha problem is that the transclusion puts an extra element around the <app-grouped-button> elements, which leads to problems because I want app-button-group to be used as a flexbox container.

Upvotes: 1

Views: 576

Answers (2)

gkalpak
gkalpak

Reputation: 48212

You can use the transclude function to get a hold of the transcluded content and append it directly to the <app-button-group> element:

app.directive('appButtonGroup', function () {
  return {
    restrict: 'E',
    transclude: true,
    template: '<h4>This is a button-group:</h4>',
    link: function (scope, elem, attrs, ctrl, $transclude) {
      $transclude(function (content) { elem.append(content); });
    }
  };
});

See, also, this short demo.

Upvotes: 1

noypi
noypi

Reputation: 991

ng-transclude is not required for transclusion, you can also use, the transclude function. might help:

$transclude(scope,function(clone){
   ...
});

Upvotes: 0

Related Questions