9

I have a component called "Node" which should display a single post, but I have more than a post type and each type has its own view (layout).

So this component has an ID parameter which will be used to get a post response from a service then according to post type it should display the correct layout.

ex: localhost/test_app/node/123 where 123 is the id parameter.

Approach 1: using ngIf in the tamplate

@Component({
  selector: 'node',
  directives: [Post, Project],
  template: `
    <post *ngIf="response.post.post_type == 'post'" content="response.post"></post>
    <project *ngIf="response.post.post_type == 'project'" content="response.post"></project>
  `,
})

export class Node{

  id: number;
  response: any;
  constructor(private _param: RouteParams,
              public service: Service
  ){
    this.id = +_param.get('id');
  }

  ngOnInit(){
    this.service.get(this.id).subscribe(
      res=> this.response = res.json()
    );
  }

}

Approach 2: using dynamic component loader.

@Component({
  selector: 'node',
  directives: [Post, Project],
  template: '<div #container></div>'
})

export class Node{

  id: number;
  response: any;

  constructor(private _param: RouteParams,
              public service: Service,
              private loader:DynamicComponentLoader,
              private elementRef:ElementRef
  ){
    this.id = +_param.get('id');
  }

  ngOnInit(){
    this.service.get(this.id).subscribe(
      res=> {
          this.response = res.json();
          this.renderTemplate();
      }
    );
  }

  renderTemplate(template) {
    this.loader.loadIntoLocation(
      this.getCorrectTemplate(),
      this.elementRef,
      'container'
    )
  }

  getCorrectTemplate(){
    if(this.response.post.post_type == "post"){
        return '<post content="response.post"></post>';
    }
    else{
        return '<project content="response.post"></project>';
    }
  }

}

I'm wondering which approach is more efficient or if there is a better approach, please share it.

Community
  • 1
  • 1
Murhaf Sousli
  • 12,622
  • 20
  • 119
  • 185
  • I prefer the JavaScript conditional like while we working in some project we faced lot of issues regarding performance as we were lot of conditional filtering on template and we move all that to JavaScript it show massive performance improvement. – Arpit Srivastava Jun 06 '16 at 04:09
  • @ArpitSrivastava In Angularjs or Angular2? – Günter Zöchbauer Jun 06 '16 at 04:34
  • @GünterZöchbauer In Angularjs – Arpit Srivastava Jun 06 '16 at 04:44
  • @ArpitSrivastava you can't apply such experience from Angularjs to Angular2. They are entirely different frameworks and performance improvements are huge in Angular2 compared to Angular.js. – Günter Zöchbauer Jun 06 '16 at 04:46
  • @GünterZöchbauer yup that true but may the approach is same for ng-if as functionality is same in both are same – Arpit Srivastava Jun 06 '16 at 04:53
  • It's not well supported to switch the template in JS anyway in Angular2. In Angular2 you usually just modify the model and let Angular control the DOM, otherwise you're working against the framework. – Günter Zöchbauer Jun 06 '16 at 04:55

1 Answers1

3

If you have a limited set of possible templates then *ngIf or *ngSwitch is a good approach. It allows you to use [] and () bindings between parent and child.

If you have a set of templates that are statically unknown and for example provided by a parameter then *ngIf doesn't work. Then ViewContainerRef.createComponent() (replaces DynamicComponentLoader) is the right approach. For an example see Angular 2 dynamic tabs with user-click chosen components

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • in the answer's link, I'm getting error in webstorm on `this.type`, in updateComponent: `this.resolver.resolveComponent(this.type).then...` – Murhaf Sousli Jun 06 '16 at 04:45
  • What's the exact error message? Types usually aren't necessary to run TS but static analysis might require them, depending on the configuration. I'm not familiar with this kind of configuration because I use TS only in Plunker and use Dart to develop with Angular2. – Günter Zöchbauer Jun 06 '16 at 04:48
  • `unresolved variable type` it's expecting to define `type` in the component – Murhaf Sousli Jun 06 '16 at 04:50
  • It should refer the variable `@Input() type` (at the top of the class). If it is there, the error doesn't make sense to me. How much did you change the code? Can you try to reproduce in the Plunker? – Günter Zöchbauer Jun 06 '16 at 04:53
  • ohh my bad, I'm using the id instead of the input so I removed it. lol – Murhaf Sousli Jun 06 '16 at 04:54
  • Ok, glad to hear you found the cause :) – Günter Zöchbauer Jun 06 '16 at 04:56