流星分页问题(Meteor Pagination Issue)

HTML/CSS IT屋
百度翻译此文   有道翻译此文
问 题

I am having issues with pagination I've implemented. Pagination works based on server-sided publish skip & limit filter.

Issue #1. If I perform a specific user search the very first page will be blank. enter image description here

At that state skip is set to 0, limit is always 20.

If I perform a find().fetch() I get 20 elements, but they are all for a different user. enter image description here

Issue #2 Me going to next page (skip+10) gives me a few more elements enter image description here

Doing it again gives even more results enter image description here

and finally being out of data, and going to next page just removes 10 results, leaving 10 shown enter image description here

This is a very odd behavior. Server-sided publish

Meteor.publish('overtime', function(opt){
if (!Roles.userIsInRole(this.userId, 'admin')) {
return Overtime.find({userId: this.userId}, opt);
} else {
return Overtime.find({}, opt);
}
});

Client-sided subscription

var defaultSkipStep = 10;
var defaultLimit = 20;
Template.triphtml.onCreated(function(){
 var instance = this;
 Session.set('limit',defaultLimit);
 instance.autorun(function(){


instance.subscribe('overtime', {skip:(Session.get('overSkip')||0), limit:(Session.get('limit')||defaultLimit), sort: {createdAt: -1}});
instance.subscribe('trips', {skip:(Session.get('tripSkip')||0), limit:(Session.get('limit')||defaultLimit), sort: {createdAt: -1}});
});

Next page click event

"click .nxtpage_over": function(event, template){
Session.set('overSkip', (Session.get('overSkip') || 0) + defaultSkipStep);
Session.set('limit', 20);
},

Submit event https://pastebin.com/btYCSQBD

Query that user sees main.js (client)

https://pastebin.com/tWakPDT1

main.html https://pastebin.com/4uMVFsNG

Any idea how to make it so that when I perform search for a specific user I get all 20 results just for that user, and next page gives me NEXT 20 elements, not showing any one the 20 I've just seen.

解决方案

Use below code for pagination. It is very ideal code, easy to understand and implement.

SERVER PUBLISH:

        Meteor.publish('Students', function (str, toSkip, tillLimit) {
        var regex = new RegExp(str, 'i');
        var data = Students.find( {
                                $or:[
                                    {"_id": {'$regex' : regex}},
                                    {"username": {'$regex' : regex}}
                                ]
                            },
                    {sort: {'time': -1}, skip: toSkip, limit : tillLimit});
      return data;
    });

    Meteor.publish('StudentsTotalCount', function (str) {
        var regex = new RegExp(str, 'i');
        Counts.publish(this, "StudentsTotalCount", Students.find({
                                $or:[
                                    {"_id": {'$regex' : regex}},
                                    {"username": {'$regex' : regex}}
                                ]
                            });
          );
    });

str is global search text from client side. Now, Since the user will click on next and previous button frequently. On the client side the Subscription must be reactive. For that you can you below code.

CLIENT SUBSCRIBE:

Inside some App_ShowStudents.js file, you can create subscription as below;

    Template.App_ShowStudents.onCreated(function(){
      this.userId = new ReactiveVar("");
      this.filterCriteria = new ReactiveVar("");
      //PAGINATION
      this.enablePrevious = new ReactiveVar(false);
      this.enableNext = new ReactiveVar(true);
      this.skip = new ReactiveVar(0);
      this.diff = new ReactiveVar(0);
      this.total = new ReactiveVar(0);
      this.limit = new ReactiveVar(10);

      this.autorun(() => {
        Meteor.subscribe('Students', this.filterCriteria.get(), this.skip.get(), this.limit.get());
        Meteor.subscribe('StudentsTotalCount', this.filterCriteria.get(), this.role.get());
      });
    }); 

HELPERS:

    Template.App_ShowStudents.helpers({
        students(){
            return Students.findOne({}); // this will always be less or equal to 10.
        },
          skip(){
            return Template.instance().skip.get();
          },
          diff(){
            var instance = Template.instance();
            var add = instance.skip.get() + instance.limit.get();
            var total = instance.total.get();
            var diff = (add >= total ? total : add);
            instance.diff.set(diff);
            return instance.diff.get();
          },
          total(){
            Template.instance().total.set(Counts.get('StudentsTotalCount'));
            return Template.instance().total.get();
          }
    });

total actually must be reactive and should give only count as per your search criteria, so we had a seperate publish on server.

EVENTS:

    Template.App_ShowStudents.events({
        'click .previous': function (event, template) {
             event.preventDefault();
             if(template.diff.get() > template.limit.get()){
               template.skip.set(template.skip.get() - template.limit.get());
             }
          },
        'click .next': function (event, template) {
         event.preventDefault();
         if(template.diff.get() < template.total.get()){
           template.skip.set(template.skip.get() + template.limit.get());
         }
        },
        'input #searchData': function( event, template ) {
            if ( $( event.target ).val()) { // has some value.
              template.filterCriteria.set( $( event.target ).val() );
            } else {
              template.filterCriteria.set( "" );
            }
            console.log(template.filterCriteria.get());
          },
    });

App_ShowStudents.html

    <template name="App_ShowStudents">
       {{#if Template.subscriptionsReady}}
            <body>
                <input type="text" id="searchData" class="form-control input-lg" placeholder="Search ID, Username" />
                Showing {{skip}} - {{diff}} of {{total}}
                {{#each students}}
                    ...
                {{/each}}
                <ul>
                  <li><a href="#" role="button" class="previous">Previous</a></li>
                  <li><a href="#" role="button" class="next">Next</a></li>
                </ul>
            </body>
        {{else}}
            Please wait...
        {{/if}}
    </template>

本文地址:IT屋 » Meteor Pagination Issue

问 题

我遇到了我实施的分页问题。分页工作基于服务器端发布跳过&限制过滤器。

问题#1。
如果我执行特定的用户搜索,第一页将是空白的。
在这种状态下skip设置为0,限制总是20。

$

b
$ b

如果我执行find()。fetch()我得到20个元素,但它们都是针对不同的用户。

几个元素



再次提供甚至更多 results



并最终无法访问数据,转到下一页 10条结果,显示10条



这是一个很奇怪的行为。
服务器端发布

  Meteor.publish('overtime',function(opt){
if (!Roles.userIsInRole(this.userId,'admin')){
return Overtime.find({userId:this.userId},opt);
} else {
return Overtime。 find({},opt);
}
});


客户端订阅



  var defaultSkipStep = 10; 
var defaultLimit = 20;
Template.triphtml.onCreated(function(){
var instance = this;
Session.set('limit',defaultLimit);
instance.autorun(function(){


instance.subscribe('overtime',{skip:(Session.get('overSkip')|| 0),limit:(Session.get('limit')|| (创建时间:默认限制),排序:{createdAt:-1}});
instance.subscribe('trips',{skip:(Session.get('tripSkip')|| 0),limit:(Session.get 'limit')|| defaultLimit),sort:{createdAt:-1}});
});


下一页点击事件



 “click .nxtpage_over”:function(event,template){
Session.set('overSkip',(Session.get('overSkip')|| 0)+ defaultSkipStep);
Session.set('limit',20);
},


提交事件
https://pastebin.com/btYCSQBD



查询用户看到
main.js(客户端)



https://pastebin.com/tWakPDT1



main.html
https://pastebin.com/4uMVFsNG



任何想法如何当我执行搜索某个特定用户时,我会为该用户获得全部20个结果,而下一页给出了我下一个20个元素,而不是显示我刚才看到的20个结果。


解决方案

使用下面的代码进行分页。这是非常理想的代码,易于理解和实施。



SERVER PUBLISH:



 var regex = new RegExp(str,'i'); 
var data = Students.find({
$或:[
{“_id”:{'$ regex':regex}},
{“username”:{'$ regex':regex }}
$ b $,b $ b {sort:{'time':-1},skip:toSkip,limit:tillLimit});
返回数据;
});
$ b Meteor.publish('StudentsTotalCount',function(str){
var regex = new RegExp(str,'i');
Counts.publish(this,“StudentsTotalCount “,Students.find({
$或:[
{”_id“:{'$ regex':regex}},
{”username“:{'$ regex':regex }}
]
});
);
});


str 是客户端的全局搜索文本。现在,由于用户会经常点击下一个和以前的按钮。在客户端,订阅必须是被动的。为此,你可以在下面的代码。



客户订阅

App_ShowStudents.js 文件,您可以按如下方式创建订阅;

 模板.App_ShowStudents.onCreated(function(){
this.userId = new ReactiveVar(“”);
this.filterCriteria = new ReactiveVar(“”);
// PAGINATION
this.enablePrevious = new ReactiveVar(false);
this.enableNext = new ReactiveVar(true);
this.skip = new ReactiveVar(0);
this.diff = new ReactiveVar(0 );
this.total = new ReactiveVar(0);
this.limit = new ReactiveVar(10);

this.autorun(()=> {
Meteor.subscribe('Students',this.filterCriteria.get(),this.skip.get(),this.limit.get());
Meteor.subscribe('StudentsTotalCount',this.filterCriteria .get(),this.role.get());
});
});


HELPERS:



  Template.App_ShowStudents.helpers({
students(){
return Students.findOne({}); //这将始终小于或等于10.
},
skip(){
return Template.instance()。skip.get();
},
diff(){
)var instance = Template.instance();
var add = instance.skip.get()+ instance.limit.get();
var total = instance.total.get();
var diff =(add> = total?total:add);
instance.diff.set(diff);
return instance.diff.get();
},
total(){
Template.instance()。total.set(Counts.get('StudentsTotalCount'));
return Template.instance()。total.get();
}
});


总共实际上必须是反应性的,只计算您的搜索条件,因此我们在服务器上进行了单独发布。



活动:



  Template.App_ShowStudents.events({
'click .previous':function(event,template){
event.preventDefault();
if(template.diff.get()> template.limit.get()){
template.skip.set(template.skip.get() - template.limit.get());
}
},
'click .next':function(event,template){
event.preventDefault();
if(template.diff.get )< template.total.get()){
template.skip.set(template.skip.get()+ template.limit.get());
}
},
'input #searchData':function(event,template){
if($(event.target).val()){//有一些值
template.filterCriteria.set($(event.target).val());
} else {
template.filterCriteria.set(“”);
}
console.log(template.filterCriteria.get());
},
});


App_ShowStudents.html



 < template name =“App_ShowStudents”> 
{{#if Template.subscriptionsReady}}
< body>
< input type =“text”id =“searchData”class =“form-control input-lg”placeholder =“Search ID,Username”/>
显示{{total}}
{{#每个学生}}
...
{{/每个}}的{{skip}} - {{diff}}}
< ul>
< li>< a href =“#”role =“button”class =“previous”>上一页< / a>< / li>
< li>< a href =“#”role =“button”class =“next”> Next< / a>< / li>
< / ul>
< / body>
{{else}}
请等待...
{{/ if}}
< / template>

本文地址:IT屋 » 流星分页问题

官方微信
扫一扫关注IT屋
微信公众号搜索 “ IT屋 ” ,选择关注
与百万开发者在一起
}