需要帮助,需要懒惰地加载手风琴内容

Bob*_*sey 5 lazy-loading accordion angular-material angular5

我正在使用Angular 5和mat手风琴来显示作者列表。每个作者写了多本书和文章。作者姓名出现在面板标题中,面板内容显示所有书籍,文章等。

因为我想显示100多位作者,每位作者有50多个条目,所以我不想一次填充整个手风琴和内容。我想发生的事情是,当用户单击作者时,它启动了一项服务,该服务查询数据库,然后适当地填充面板内容。如果关闭面板,则内容应保留,以便重新展开面板不会启动其他数据库查询。

因此,当我访问该页面时,我看到了作者爱丽丝,鲍勃和夏娃。当单击Alice时,该应用程序查询数据库,取回Alice的条目,呈现内容,然后手风琴展开。当我单击Eve时,应用程序应关闭Alice的面板,查询数据库,获取Eve的条目,呈现内容,最后展开面板。

如果我再次单击Alice,Eve的面板将关闭,但是由于Alice的内容已经存在,因此没有数据库查询或呈现。它只是扩展。文档说要使用ng-template,但是我不确定该怎么做,也不确定该如何做,因此在关闭面板后内容仍然保留。我不担心数据发生变化,以防万一发生变化时需要再次获取Alice的数据。

有什么最好的方法来解决这个问题吗?

谢谢!

G. Tranter的回答是正确的,我走的路正确。如果还有其他人最终出现在此页面上,这就是我最终要做的。

ngOnInit(){ 
    this.authorsRetrieved.subscribe( authors => {
        this.allAuthors = authors as Array;
        this.authorsRetrieved = new Array(
            Math.max.apply(Math, this.allTrainers.map(function(t){ return t.trainer_id; }))
        );
// as authors are added and deleted, the author_id won't equal the number of 
// authors, so get the highest id number, create an array that long
// then fill it with blanks so the keys have some value
            this.authorsRetrieved.fill([{}]);
        });
Run Code Online (Sandbox Code Playgroud)
showAuthorsWorks(authorID: Number = -1){
    if(authorID > this.authorsRetrieved.length){
      const tempArray = new Array(authorID - this.authorsRetrieved.length + 1);
      tempArray.fill([{}]);
      this.authorsRetrieved = this.authorsRetrieved.concat(tempArray);
    }
// only make the network call if we have to
// because we filled the id array, we can't just use length
if(typeof(this.authorsRetrieved[authorID][0]['manuscript_id']) === 'undefined'){
  this.authorWorksService.getAuthorWorks(authorID).subscribe( works => {
    this.worksRetrieved.splice(authorID, 0, works as Array<any>);
  });
}
Run Code Online (Sandbox Code Playgroud)

我添加了对几乎不可能的情况的检查,其中数组长度小于最大author_id。您必须创建一个由N个元素组成的空数组,然后填充该数组。如果不这样做,则空数组的长度为0,并且无法将数据推入不存在的数组元素中。即使在chrome控制台上,它说的长度是N,元素在那里,只是空的。

再次感谢!

G. *_*ter 5

如果您指的是与 ng-template 一起使用的 MatExpansionPanelContent 指令,那么所做的只是延迟加载内容,直到打开面板。它不知道它是否已经被加载。因此,如果您对诸如 {{lazyContent}} 之类的内容使用绑定表达式,则每次打开选项卡时都会对其进行求值。您需要自己管理内容缓存。一种简单的方法是通过吸气剂。

在您的组件中:

_lazyContent: string;
get lazyContent() {
    if (!this._lazyContent) {
        this._lazyContent = fetchContent();
    }
    return this._lazyContent;
}
Run Code Online (Sandbox Code Playgroud)

在你的 HTML 中加上:

<mat-expansion-panel>
    ...
    <ng-template matExpansionPanelContent>
        {{lazyContent}}
    </ng-template>
    ....
</mat-expansion-panel>
Run Code Online (Sandbox Code Playgroud)

因此 ng-template 负责延迟加载,而 getter 负责缓存内容。