How to use templateRef?

后端 未结 2 1982
情深已故
情深已故 2021-01-31 10:14

I am trying to find a way to dynamically construct a template in Angular2. I was thinking templateRef might provide a way to do this. But I could be wrong.

I found an ex

相关标签:
2条回答
  • 2021-01-31 10:41

    Creating your own template directive it's not difficult, you have to understand two main things

    • TemplateRef contains what's inside your <template> tag
    • ViewContainerRef as commented by Gunter, holds the template's view and will let you to embed what's inside the template into the view itself.

    I will use an example I have when I tried to solve this issue, my approach is not the best for that, but it will work for explaining how it works.

    I want to clarify too that you can use any attribute for your templates, even if they're already used by builtin directives (obviously this is not a good idea, but you can do it).

    Consider my approach for ngIfIn (my poor approach)

    <template  [ngIfValue]="'make'" [ngIfIn]="obj">
      This will print
    </template>
    <template [ngIfValue]="'notExistingValue'" [ngIfIn]="obj">
      This won't print
    </template>
    

    We have here two templates using two inputs each ngIfIn and ngIfValue, so I need my directive to grab the template by these two inputs and get their values too, so it would look like this

    @Directive({
      selector : '[ngIfIn][ngIfValue]',
      inputs : ['ngIfIn', 'ngIfValue']
    })
    

    First I need to inject the two classes I mentioned above

    constructor(private _vr: ViewContainerRef, private _tr: TemplateRef) {}
    

    I also need to cache the values I'm passing through the inputs

      _value: any;
      _obj: any;
    
      // Value passed through <template [ngIfValue]="'...'">
      set ngIfValue(value: any) {
        this._value = value;
      }
    
      // Value passed through <template [ngIfIn]="...">
      set ngIfIn(obj: any) {
        this._obj = obj;
      }
    

    In my case I depend on these two values, I could have my logic in ngOnInit but that would run once and wouldn't listen for changes in any of the inputs, so I put the logic in ngOnChanges. Remember that ngOnChanges is called right after the data-bound properties have been checked and before view and content children are checked if at least one of them has changed (copy and paste from the docs).

    Now I basically copy & paste NgIf logic (not so complex, but similar)

      // ngOnChanges so this gets re-evaluated when one of the inputs change its value
      ngOnChanges(changes) {
        if(this._value in this._obj) {
    
          // If the condition is true, we embed our template content (TemplateRef) into the view
          this._vr.createEmbeddedView(this._tr);
        } else {
    
          // If the condition is false we remove the content of the view
          this._vr.clear();
        }
      }
    

    As you see it's not that complicated : Grab a TemplateRef, grab a ViewContainerRef, do some logic and embed the TemplateRef in the view using ViewContainerRef.

    Hopefully I made myself clear and I made how to use them clear enough also. Here's a plnkr with the example I explained.

    0 讨论(0)
  • 2021-01-31 10:52

    ngForTemplate is only supported with ngFor

    <template [ngFor] [ngForOf]="..." [ngForTemplate]="container"
    

    or

    <div *ngFor="..." [ngForTemplate]="container"
    

    not on a plain template. It is an @Input() on the NgFor directive

    Another way to use TemplateRef

    If you have a reference to ViewContainerRef you can use it to "stamp" the template

    constructor(private _viewContainer: ViewContainerRef) { }
    
    ngOnInit() {
      this.childView = this._viewContainer.createEmbeddedView(this.templ);
      this.childView.setLocal('data', this.data);
    }
    
    0 讨论(0)
提交回复
热议问题