在指令

时间:2018-01-20 15:33:46

标签: angular user-interface user-experience ngfor inplace-editing

我正在开发一个Angular指令来检测(和删除)*ngFor列表中的空项。

我没有添加一个会触发删除的X按钮(每个项目),而是更多的基于内容的方法:如果用户删除 - 完全或只是某个关键字段 - 项目,一旦用户关注文档的另一部分,它就会不复存在。

I've managed to make it(令我惊讶的是,这并不困难)。我将在这里强调一下关键方面:

使用指令

模板

  <div *ngFor="let item of data; index as i"
    [appInPlaceDelete]="isEmpty"
    (delete)="onDelete(i)"
  >

成分

  onDelete(i: number) {
    // code to erase ith item
  }

  private isEmpty(item): boolean {
    // logic to answer if item is empty or not
  }

实施

@Directive({
  selector: '[appInPlaceDelete]'
})
export class InPlaceDeleteDirective<T> implements OnInit, DoCheck {
  @Input() appInPlaceDelete: (t: T) => boolean;
  @Output() delete: EventEmitter<undefined> = new EventEmitter();

  // ...

  private $implicit: T;
  private focusstream = new Subject<string>();

  constructor(private containerRef: ViewContainerRef) {
  }

  ngOnInit() {
    const context: NgForOfContext<T> = this.containerRef['_view'].context;
    this.$implicit = context.$implicit

    // code forwarding 'focusstream' to 'delete' output
  }

  // code that gives visual indication that the item will be deleted

  // ...
  // a bunch of @HostListeners feeding the focusstream
  // ...
}

现在,我对我的所作所为非常满意,除了之外的那一行:

    const context: NgForOfContext<T> = this.containerRef['_view'].context;

因为访问_view属性不是平台可移植的(可能此属性仅存在于platformBrowserDynamic)。

以下是问题:

  1. 有没有办法捕获context平台独立方式?
  2. NgForOf将此上下文独立于平台as seen on its source code。也许有(或应该)一种方法来便携地检索该上下文。我知道,开发人员(我)仍然有责任知道该上下文的含义(类型)。坚持下去,这是下一个问题。

    1. 我是否可以使selector限制性更强,只能在*ngFor主机内部进行挂钩?
    2. 对于这个我知道我们应该记住,角度将原始模板翻译为:

      <ng-template ngFor let-item [ngForOf]="data" let-i="index">
        <div
          [appInPlaceDelete]="isEmpty"
          (delete)="onDelete(i)"
        >
      </ng-template>
      

      因此,divs指令动态创建的嵌入式视图中指示的实际NgForOf

      我想知道是否有某种方法可以强制执行此操作(我尝试selector: '[ngFor] > [appInPlaceDelete]'无效)。

      1. 有解决方法吗?
      2. delete输出显然使用了上下文变量i(指令本身对i一无所知;它只是通过delete频道发出事件。

        虽然我事先知道它会将[appInPlaceDelete]="isEmpty(item)"绑定到false,但我尝试了appInPlaceDelete

        我还尝试[appInPlaceDelete]="() => isEmpty(item)"...="function() { return isEmpty(item); }"期望此角度会创建一个抓取item(和isEmpty)的闭包并传递该闭包。也没有成功。

        虽然有点难看,但这比非便携式指令要好。

        1. Iff没有其他方法可以回答第一个问题,也没有第三个问题的解决方法,我怎样才能覆盖至少最常见的平台?
        2. 虽然不可取,但也许我可以通过某种方式确定我的指令在哪个平台上运行并专门访问context

          在这件事情上我必须承认我不知道如何使用(甚至更少调试)除platformBrowserDynamic以外的任何其他内容。

          1. 如果你到目前为止,还有其他完全不同的做法吗?
          2. 本文中的前两段描述了我在这里要完成的任务。其他一切只是我的解决方案(以及它带来的问题)。

            也许有一种完全不同的做法。也许有人已经/打包/发布了更好的解决方案。

0 个答案:

没有答案