3

So everything should be a component.

Suppose I define some button components for editing/deleting/viewing my domain objects. As an example:

angular.module('xxx').component('editButton', {
  bindings: {domainObject: '<'},
  template: '<button class="btn btn-default" ng-click="$ctrl.displayEditForm()">Edit</button>'
  controller: /* ... */
});

And I use it as:

<edit-button domain-object="$ctrl.myDomainObject"></edit-button>

Works great! However, when I need a specific markup (for example a button group), I'm trying to do it as:

<div class="btn-group">
  <edit-button domain-object="object"></edit-button>
  <delete-button domain-object="object"></delete-button>
</div>

Which of course is not displayed correctly by Bootstrap because my buttons are wrapped with the component definitions.

Keeping in mind that the replace functionality is deprecated, I wonder how to overcome this problem ?

Community
  • 1
  • 1
fracz
  • 20,536
  • 18
  • 103
  • 149
  • If you talk about abstract ideal component - it should has its own css. If you talk about real world - you still need directives in angular 1.5 and there In angular 2 you can match components to html attributes too not just elements. – Petr Averyanov Jun 16 '16 at 00:10
  • So you say I would be able to create `@Component({selector: '[my-component]'})` in Angular 2? This would solve the problem, indeed! Can you post it as an answer, please? – fracz Jun 16 '16 at 05:04
  • I have just found [attribute directives](https://angular.io/docs/ts/latest/guide/attribute-directives.html). They will solve the problem in Angular 2. As for 1.5, the solution is to use the `replace` despite its deprecation or a directive with `restrict: 'A'`. So simple! – fracz Jun 16 '16 at 05:11

1 Answers1

2

A component is not always an html element. It can be (and often is a group of html elements)

Your component template should include the surrounding div btn-group.

template: '<div class="btn-group"><button class="btn btn-default" ng-click="$ctrl.displayEditForm()">Edit</button>'...etc.

Now if you want to reuse buttons individually, you can just override bootstrap's styles so that they don't use '>'

.your-page .btn-group .btn:first-child:not(:last-child):not(.dropdown-toggle) {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

instead of

.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle) {
        border-top-right-radius: 0;
        border-bottom-right-radius: 0;
}
gyc
  • 4,300
  • 5
  • 32
  • 54
  • 1
    I want to avoid having all buttons in one component as it violates SRP (the major benefit from components for me). Duplicating CSS code from bootstrap is also *far from perfect* solution (I suppose there is more to copy&paste than you suggests). Nevertheless, your ideas solve the problem *somehow*, thank you. – fracz Jun 15 '16 at 22:47
  • In a component-based application you will definitely have components containing many elements and other child components. (see the hero list example in the angular doc) I think you're pushing the SRP theory to an extreme. Here the component would have the responsability of controlling your object's state. – gyc Jun 15 '16 at 22:56
  • 1
    Of course components can create hierarchies. But the only responsibility of `my-button-group` component should be grouping others, specialized components like `edit-button` and `delete-button`. If `my-button-group` component would have to take care about object editing and deletion details, its code will grow with each new button added. This would certainly be a badly-designed-component. – fracz Jun 15 '16 at 23:00