Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 可观察<;对象[]>;-我可以跳过/拿走吗?_Angular_Rxjs_Observable_Infinite Scroll - Fatal编程技术网

Angular 可观察<;对象[]>;-我可以跳过/拿走吗?

Angular 可观察<;对象[]>;-我可以跳过/拿走吗?,angular,rxjs,observable,infinite-scroll,Angular,Rxjs,Observable,Infinite Scroll,我想在我的对象列表上无限滚动,它们是可观察的。将它们转移到promise并等待它们不是一个选项,因为它们需要实时更新 我所做的是使用.map()哪种方法有效,但问题是angular每次使用20项而不是10项时都会重新呈现整个列表 一种解决方案是实际跳过第一个10,然后加载下一个10,这样只会向页面添加新元素。但是我不确定这是否可能 这是我的 打字稿 // Every time this happens page goes to top // because all the items are r

我想在我的对象列表上无限滚动,它们是可观察的。将它们转移到promise并等待它们不是一个选项,因为它们需要实时更新

我所做的是使用
.map()
哪种方法有效,但问题是angular每次使用
20
项而不是
10
项时都会重新呈现整个列表

一种解决方案是实际跳过第一个
10
,然后加载下一个
10
,这样只会向页面添加新元素。但是我不确定这是否可能

这是我的

打字稿

// Every time this happens page goes to top
// because all the items are re-rendered, not only new ones
public onScroll(): void {
  this.take += 10; // on ngOnInit() take is set to 10.
  this.sales = this.filteringObservable.map(data => {
    return _.take(data, this.take);
  });
}
HTML


以下是我在这个场景中使用的一些代码:

private-filterModel:filterModel=new-filterModel();
专用页:编号=0;
项目:结果模型[]=[];
public onScroll():void{
如果(这是滚动){
返回;
}
this.scrolling=true;
这个.page++;
this.service.loadStuff(this.filterModel,this.page).subscribe(items=>{
!items | |!items.length
?本页--
:items.forEach(item=>this.items.push(item));
this.scrolling=false;
},
()=>this.scrolling=false);
}
其中,
filterModel
是一个对象,其中包含有关加载内容和加载方式的数据—页面大小、属性过滤器等

如果您想以更为RxJs的方式实现这一点,您可以尝试以下方式(未经测试,根据需要进行调整):

private-filterModel:filterModel=new-filterModel();
私有筛选器$=新主题();
专用页:编号=0;
私有页$=新主题();
专用缓存:ResultModel[]=[];
项目$:可观察;
恩戈尼尼特(){
const filter$=此.filter$.pipe(
去BounceTime(1000),
distinctUntilChanged(),
轻触(()=>this.cache=[]),
映射(model=>({model:this.filterModel=model,page:0}))
);
const page$=此.page$.pipe(
映射(pageNumber=>({model:this.filterModel,page:pageNumber}))
);
this.items$=合并(页面$,过滤器$).pipe(
startWith({model:this.filterModel,page:this.page}),
点击(()=>this.scrolling=true)
合并映射({model:FilterModel,page:number})=>
this.service.loadStuff(model,page).pipe(
点击(response=>this.cache[page]=response.items)
)
),
点击(response=>…),//在此处对您的响应执行任何其他操作
map(()=>u2;.flatMap(this.cache)),
点击(()=>this.scrolling=false)
);
}
onScroll(){
this.page$.next(this.page++);
}
onFilter(型号:FilterModel){
this.filter$.next(模型);
}

希望这能指引你正确的方向:)

这很容易实现,我有多个类似这样的列表

首先,你想使用某种库,我使用

然后您希望您的列表使用它:

<ul infiniteScroll (scrolled)="getItems()">
  <li *ngFor="let item of items; trackBy:trackByFn">{{item}}</li>
</ul>

trackByFn(i: number, item) {
  return item.<unique-key>;
}
确保用每个项目的唯一键替换


我希望这能有所帮助。

这就是我们如何使用Angular 5和WebApi作为服务器端来实现这一点。我们已经在我们的表中实现了某种排序,但是您可以使用部分滚动,并在列表中使用它。此外,我们从表中获取所有数据,然后以10行为单位发送给客户端,但如果需要速度,可以在SQL server中分页数据,一次只获取10行。如果您需要这种分页的逻辑,请告诉我。

HTML 角分量 WebAPI服务
公共列表SearchSales(字符串sorttype、字符串sortad、ref int count)
{
var query=“”;
query=“从销售中选择*”+
“订单依据”+((sorttype==null)?“销售日期”:sorttype)++((sortad==null)?“描述”:sortad);
var result=SQLHelper.ExecuteReader(查询);
计数=结果。计数;
返回结果;
}

所以你是累积项目,比如10、20、30、40,。。但是您总是希望只显示最后一批?顺便说一句,这看起来更像是一个问题,因为您没有在
*ngFor
中使用
trackBy
。请参阅@martin No,每当我滚动到底部时,我想再添加10个项目。
<ul infiniteScroll (scrolled)="getItems()">
  <li *ngFor="let item of items; trackBy:trackByFn">{{item}}</li>
</ul>

trackByFn(i: number, item) {
  return item.<unique-key>;
}
// isReset decides whether to set offset to 0 or not
getItems(isReset = false): void {

    if (!isReset && this.items.length >= this.total) {
      return;
    }

    this.api.get<CustomResponse>('my-api-endpoint', {
      limit: 10,
      offset: isReset ? 0 : this.items.length,
    })
      .pipe(
        first(),
        tap((res) => this.total = res.totalsize || 0),
        map((res) => res.list)
      )
      .subscribe((items) => {

        // This bit prevents the same batch to be loaded into the list twice if you scroll too fast
        if (this.items.length && !isReset) {

          if (items[items.length - 1].<unique-key> === this.items[this.items.length - 1].<unique-key>) {
            return;
          }
        }

        this.items = isReset ? items : [...this.items, ...items];
      })
    );
  }
<div #scb id="scb" class="scrollBarClass" *ngIf="sales && sales.length" (scroll)="onScroll()">
    <div class="table table-striped table-responsive table-sm table-bordered">
        <table class="table" *ngIf="sales && sales.length">
        // here goes you table structure, headers, body and so...
        </table>
    </div>
</div>
.scrollBarClass {
  max-height: 500px;
  overflow-y: scroll;
}
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';

@ViewChild('scb') grid: ElementRef;
scroll = false;
page = 1; 
total = 0;   

onScroll() {
    if (this.grid.nativeElement.scrollHeight - this.grid.nativeElement.scrollTop < 510 && this.scroll == false) {
        if (this.sales.length == this.total) {
            return;
        }
        let p: any;
        this.page++;
        this.scroll = true;
        this._myService.searchSales(this.page, 10, this.sortType, this.sortAD)
            .subscribe(
                (data) => { p = data['data']; this.total = data['count']},
                error => { this.errorMessage = <any>error; this.page--; },
                () => {
                    this.scroll = false;
                    Array.prototype.push.apply(this.sales, p);
                });
    }
}
searchSales(page: number, recperpage: number, sorttype: string, sortad: string) {
    let params = new HttpParams()
        .append('page', page.toString())
        .append('recperpage', recperpage.toString())
        .append('sorttype', sorttype)
        .append('sortad', sortad);
    return this._http.get<any[]>('sales/searchsales', { params: params });
}
[HttpGet]
public IHttpActionResult searchsales(int page, int recperpage, string sorttype, string sortad)
{
    try
    {
        var count = 0;
        var r = _salesService.SearchSales(sorttype, sortad, ref count);
        return Ok(new { data=r.Skip((page - 1) * recperpage).Take(recperpage).ToList(), count });
    }
    catch (Exception e)
    {
        return InternalServerError(e);
    }
}
public List<Sales> SearchSales(string sorttype, string sortad, ref int count)
{
    var query = "";

    query = " select * FROM Sales "+
            " ORDER BY " + ((sorttype == null) ? "DateOfSale" : sorttype) + " " + ((sortad == null) ? "DESC" : sortad);
    var result = SQLHelper.ExecuteReader(query);
    count = result.Count;
    return result;
}