19

How can I give an Angular 2 component multiple views\view templates?

Do I have to use ng-content? Which is not exactly the function I want. Maybe a component property that specifies the template url, but then how to change the view\template in the component class?

rethenhouser2
  • 400
  • 1
  • 3
  • 14

5 Answers5

11

Today also think about this problem. I "invent" this solution http://plnkr.co/edit/FYVwbBwSnqWRcvAVz3wh?p=preview . May be it helps You in future.

export class MyModel {
  lala;
  constructor() {
    this.lala = "llaala";
  }
  appendToLala(param: string){
    this.lala += param;
  } 
}

@Component({
  selector: 'c1',
  template: `<div><h2>Hello {{lala}}</h2></div>`,
})
export class Component1 extends MyModel {
  constructor(){
    super();
    this.appendToLala(" bebebe");
  }
}


@Component({
  selector: 'c2',
  template: `<div><h2>Hello {{lala}}</h2></div>`,
})
export class Component2 extends MyModel {
  constructor(){
    super();
    this.appendToLala(" nenene");
  }
}

The idea is to create an abstract component model and use it as @Component's parent. And if needed, You can create a tree from models and @Component class will always be a leaf in this tree.

karina
  • 789
  • 9
  • 26
3

The ng-content is to be used to define where you want the content of your component to go, explanation follows :

Say you define your own component with its template and a selector 'my-cmp', if you use it as such : <my-cmp><div>content</div></my-cmp>, the div inside your component must go somewhere, that is what you define in the template when you implement my-cmp. Say : <h1>my component title</h1><ng-content></ng-content> your div will go where the ng-content is placed.

Now if you want to have multiple views I believe it's a design issue, and it would most likely be two different components, and then a parent container would contain them both. This parent container could communicate with your service and give your child components the model they need to display themselves. They could emit an event when the user does something, that the parent catches, triggers a service call, and feeds them the updated model through data binding.

Or if you want to display one or the other maybe it can be handled with routes ?

Or a last way would be a ng-if, if you have a certain state in your model then display one child component, otherwise display the other.

If you are a bit more specific about the need you have I could mock up some code.

Arnaud Boeglin
  • 763
  • 6
  • 12
  • Really what I want is to not have the component coupled to the view at all, so I can use it like I would a controller in angular 1 with ngController anywhere I like, composing my app in views mvvm style. – rethenhouser2 Aug 06 '15 at 11:51
  • Check out here : [link]http://stackoverflow.com/questions/31692416/dynamic-template-urls-in-angular-2[/link]. I believe you could define a property view-url that is a string so you could call , and the template : templateUrl : (function() { return this.viewURL; } ). Even though I'm not certain about the use case since different views may need to handle things a little differently, but it seems it is possible. Maybe you need a directive ? It is a Component without a View, so you could have functionnality applied to different views. – Arnaud Boeglin Aug 06 '15 at 13:27
0

This is how I handled it, although I don't love the solution:

  • I have a component myComponent which renders to selector: 'my-component'.
  • In my main app, I create two variables target:string = 'template-one' and target2:string = 'template-two'.
  • I create two instances of the component in my app template which looks like <my-component [target]="target"></my-component> and <my-component [target]="target2"></my-component>.
  • Lastly, in the template for my-component, I have two different blocks of markup, the first intended for when target === "template-one" and the second for when target === "template-two". On the outer html element for one I put *ngIf="target === 'template-one'" and on the outer html element for the other I put *ngIf="target === 'template-two'" which effectively creates a fork in the rendering.

I may post back if I come up with something better, but for now this is the best I could do with what Angular 2 gave me.

autoboxer
  • 1,358
  • 1
  • 16
  • 37
0

Not sure if NG2 has built-in way to support this.

It looks like you need two components, but you have one, and you tying to find a fastest way. But the best solution will be split complicated logic into different structures (like services, other modules etc). The best way it to make the structure that will be comfortable to work with. And when you build this structure - you will not need to multiple html to the directive.

qiAlex
  • 4,290
  • 2
  • 19
  • 35
0

If you are simply trying to change what is displayed in a view for a single user session based on the value of a variable in your component, you could consider containing your html in different div elements and use ngIf or ngSwitch to switch between them.

A quick and cheap example, if you have a boolean variabled named "loading" in your component you can switch between what is displayed like so:

<div *ngIf="loading">
    <h1>Loading...</h1>
</div>

<div *ngIf="!loading">
...
</div>
Derek
  • 126
  • 1
  • 7