-1

An interesting question arose.

There is a component that listens for a subject like:

export interface ToolPanel {
     title ?: string;
     buttons: Button [];
}

And then it just displays the buttons in the ngFor template.

Now you need to add the ability to display select list or textarea under the buttons?

How to properly extend the functionality of a component (template)?

Template is:

<div class="row" *ngFor="let tool of tools.toolPanels$">
     {{tool.title}}
     <!-- Here can be input, select or textarea -->
</div>

I think to extend the interface:

export interface ToolPanel {
     title ?: string;
     buttons: Button [];
     type: 'formField'
}

Then check in template:

<div class="row" *ngFor="let tool of tools.toolPanels$">
     {{tool.title}}
     <div *ngIf="tool.type === 'formField'">
       <app-formfield [type]="tool.type"></formfield>
     </div>
</div>

1 Answers1

0

If i understood you right there are multiple ways to achive what you want but none of them are providing a full component extension because you can not extend templates and decorators in angular. Some people even say you should not use inheritance in angular, instead go with services for code reuse...

...but to reuse components functionallity you could put a <ng-content> tag inside your basecomponent and then manage the additonal content from the outside like:

BasePanelComponent

<div class="row" *ngFor="let tool of tools.toolPanels$">
     {{tool.title}}
     <ng-content>
</div>

Usage

<app-base-panel [tools]="tools">
     <!-- Here can be input, select or textarea -->
</app-base-panel>

Or you create multiple components that extend your base component and have their own template. Like:

BasePanelComponent

@Directive()
export class BasePanelDirective {

  @Input() config: ToolPanel;

  constructor() { }

}

InputFieldPanelComponent...

@Component({
             selector:    'app-input-field-panel',
             templateUrl: './input-field-panel.component.html',
             styleUrls:   ['./input-field-panel.component.scss'],
           })
export class InputFieldPanelComponent extends BasePanelDirective {

}

That way you have to copy the html code but can reuse the ts functions.

Or you do it like you did and use the *ngIf directive.

Conclusion:

If you have only a few places where this component should be used i would go with the <ng-content> approach. If you use the components a lot, i would go with an own template for each of them approach. If the changes are small enough you can use your *ngIf approach.

Read more on:

How to extend / inherit components?

https://ozak.medium.com/stop-repeating-yourself-in-angular-how-to-create-abstract-components-9726d43c99ab

https://github.com/angular/angular/issues/7968

thecOdemOnkey
  • 271
  • 2
  • 6
  • is it okay that component responsible for create buttons and form elements? –  Jun 05 '21 at 12:49
  • @Mamkad: If you want to create a form with dynamic components (?) you could create a base ControlValueAccessor and then use the components where the form is. If you want the buttons click to be handled outside the \ approach is also working well or you pass it along with an @Output() onExecute: EventEmitter or something? – thecOdemOnkey Jun 05 '21 at 13:01
  • @Mamkad And btw. this is only based on my work with angular i never learned how to do it the right way but i had the same problems trying to keep my code DRY. Just try not to be too strict is what i learned. – thecOdemOnkey Jun 05 '21 at 13:10