3

What I want to achieve

I have a CRM panel I am building for practice. That CRM panel has pages, and a navigation on the left side of the screen.

Each page should display the title.

That means that I have to include <h2>title</h2> in every component template.

Solution that I thouht of

What if I create a component PageBaseComponent that gets title:

@Component({
  selector: 'app-page-base',
  templateUrl: './page-base.component.html',
  styleUrls: ['./page-base.component.scss']
})
export class PageBaseComponent implements OnInit {

  constructor(private title: string) { }

  ngOnInit() {
  }

}

And then inherit it whenever I have a new page:

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent extends PageBaseComponent implements OnInit {

  constructor() {
    super("Dashboard");
   }

  ngOnInit() {
  }

}

And in the template of PageBase I do

<h1>{{title}}</h1>

And in my component that inherits its I can do something like this IF possible:

<parent-component-html></parent-component-html>

my page info here blab blabla

Is it possible to do? What is the right way to achieve that structure?

Ben Beri
  • 1,101
  • 4
  • 23
  • 64
  • https://stackoverflow.com/questions/41464871/update-parent-component-property-from-child-component-in-angular-2 you need a two-way databinding, – Isitar Nov 18 '18 at 21:55
  • you may just use a router. put in your base component and route your child components in the outlet. If you cannot use router, you may try include both a header and a content component in the same page(a page component) – wctiger Nov 18 '18 at 21:57
  • @wctiger How is that related to routing? I already do routing to render HomeComponent – Ben Beri Nov 18 '18 at 22:01
  • @BenBeri see whether [this angular doc](https://angular.io/guide/router#a-crisis-center-with-child-routes) may be helpful – wctiger Nov 18 '18 at 22:04

1 Answers1

3

Your idea of creating a base component PageBaseComponent is pretty good. However, in Angular such shared functionality is implemented differently.

I would suggest you to look at angular transclusion. In your example the PageBaseComponent doesn't have much functionality in it. The main point - is sharing a template.

So, in this scenario you could create a PageBaseComponent component the following way:

@Component({
  selector: 'app-page-base',
  templateUrl: './page-base.component.html',
  styleUrls: ['./page-base.component.scss']
})
export class PageBaseComponent implements OnInit {

  @Input() title: string;
  constructor() { }

  ngOnInit() {
  }

}
<h1>{{title}}</h1>
<ng-content></ng-content>

Then in all of your pages that you want to use the same base behaviour in the template you write the following:

<app-page-base [title]="'Some Title'">
  <!-- Current Page Content -->
</app-page-base>

The <ng-content></ng-content> in the PageBaseComponent will be replaced by what you put in between the <app-page-base></app-page-base> tags.

This way you can create any base layout that you want inside the PageBaseComponent and share it across all pages.

The logic here stays decoupled. That may be a good or a bad thing depending on what you want.

In order to create some base shared logic for multiple components, you would want to create a simple class - without @Component decorator. And then extend it with your components. Notice, that components work with the Angular dependency injection system. So, when you write some variable into the component's constructor, Angular tries to resolve it with its DI system. In your example it would fail.

So, to summarize - if you want to create shared template use transclusion. If you want to create shared behaviour - use base classes (without Component decorator).