【问题标题】:Angular 2 Custom Structural Directive binding using template input variable is not working使用模板输入变量的Angular 2自定义结构指令绑定不起作用
【发布时间】:2016-11-11 13:21:18
【问题描述】:

我创建了一个类似于ngFor 的自定义结构指令。当我尝试使用 <template> 元素语法使用它时,模板内的绑定正在工作,但是当我使用 * 语法时,绑定不起作用。

   <!-- 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>

这是此问题的plnkr link

我做错了什么?

更新: 我想,现在我明白发生了什么。 let-val 被错误地设置为用于绑定的对象的属性val,但我需要整个对象。因此,let-val 不应在模板中分配任何值,然后我必须更新 context.$implicit 与用作 viewRef 中的绑定源的对象。

工作plnkr here.

感谢@robisim74

【问题讨论】:

    标签: angular angular2-template angular2-directives


    【解决方案1】:

    试试这个:

    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);
            });
          }
        }
      }
    
    }
    

    然后修正模板:

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

    我关注了这篇文章:http://teropa.info/blog/2016/03/06/writing-an-angular-2-template-directive.html

    【讨论】:

    • 我从您的示例中收集到的是我需要设置 context.$implicit 与用于绑定的对象,但我不明白为什么。请你解释一下?
    • 不只是这个。为了可以使用语法*edit,您需要通过DoCheck 接口实现,特别是它的forEachAddedItem 方法来实现自定义更改检测,否则Angular 2 Change Detection 检测到值没有变化并且不会更新视图。
    • 谢谢,但我认为 DoCheck 和其他变更检测机制只是为了提高效率而不是创建结构指令的强制要求。我已经使用有效的 plnkr 链接更新了我的问题。
    • 确实它们对于创建指令不是必需的,但请注意,如果您在未检测到更改的情况下从列表中动态添加或删除项目,您将不会看到更新视图。我很高兴你最终以你想要的方式解决了问题。问候
    【解决方案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;
            });
    
          } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-07
      • 2017-07-21
      • 2019-05-26
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      • 2020-01-01
      相关资源
      最近更新 更多