Angular 2 Custom Structural Directive binding using template input variable is not working

雨燕双飞 提交于 2019-12-12 17:05:47

问题


I have created a custom structural directive similar to ngFor. When I try to use it using <template> element syntax, the binding inside the template is working but when I use * syntax, the binding is not working.

   <!-- working -->
    <template edit [editOf]="values" let-val="val">
      <table >
        <span>This is using template syntax {{val}}</span>
      </table>
    </template>

    <!-- not working -->
      <table *edit="let val1 of values">
        <span>This uses star syntax {{val1}}</span>
      </table>

Here is the plnkr link for this issue.

What am I doing wrong?

Update: I think, now I understand what is going on. The let-val is incorrectly set to a property val of object used for binding but I need the whole object. So, the let-val shouldn't be assigned with any value in the template and then I'll have to update the context.$implicit with the object used as binding source in the viewRef.

Working plnkr here.

Thanks to @robisim74


回答1:


Try this:

import {  ChangeDetectorRef,
  Directive,
  Input,
  DoCheck,
  IterableDiffer,
  IterableDiffers,
  TemplateRef,
  ViewContainerRef,
  EmbeddedViewRef} from "@angular/core";

@Directive({
  "selector":"[edit][editOf]"
})
export class EditableTableDirective implements DoCheck {

  private collection:any;
  private differ:IterableDiffer;
  private viewMap:Map<any,EmbeddedViewRef> = new Map<any,EmbeddedViewRef>();

  constructor(
    private changeDetector:ChangeDetectorRef,
              private differs:IterableDiffers,
              private template:TemplateRef,
              private viewContainer:ViewContainerRef){
  }

  @Input() set editOf(coll:any){
    this.collection = coll;
    if (coll && !this.differ) {
      this.differ = this.differs.find(coll).create(this.changeDetector);
    }
  }

  ngDoCheck() {
    if (this.differ) {
      const changes = this.differ.diff(this.collection);
      if (changes) {
        changes.forEachAddedItem((change) => {
          const view = this.viewContainer.createEmbeddedView(this.template, change.item);
          view.context.$implicit = change.item;
          this.viewMap.set(change.item, view);
        });
        changes.forEachRemovedItem((change) => {
          const view = this.viewMap.get(change.item);
          const viewIndex = this.viewContainer.indexOf(view);
          this.viewContainer.remove(viewIndex);
          this.viewMap.delete(change.item);
        });
      }
    }
  }

}

Then correct the template:

<table *edit="let item of values">
   <span>This uses star syntax {{item.val}}</span>
</table>  

I followed this article: http://teropa.info/blog/2016/03/06/writing-an-angular-2-template-directive.html




回答2:


 <tr *cpLoop="let cat of categories" (click)="selectCategory(cat)">
                <td>{{cat.categoryId}}</td>
                <td>{{cat.categoryName}}</td>
 </tr>  

 <ng-template cpLoop let-cat [cpLoopOf]="categories" let-i="index">
                 <tr (click)="selectCategory(cat)">                        
                        <td>{{cat.categoryId}}</td>
                        <td>{{cat.categoryName}}</td>
                </tr>            
  </ng-template> 

 @Input() set cpLoopOf(rows:any){
         rows.forEach((row:any, index:any) => {
          let viewRef = this.viewContainer.createEmbeddedView(this.template, row); 
          viewRef.context.$implicit =row;
        });

      } 


来源:https://stackoverflow.com/questions/38275700/angular-2-custom-structural-directive-binding-using-template-input-variable-is-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!