Sencha Touch порядок сортировки со списком пейджингового плагина

56
7

Мой бэкэнд - Parse BAAS. Чтобы сначала получать последние записи и разбивать на страницы по предыдущим записям, мне нужно будет упорядочить спуск по созданной временной отметке и использовать "пропустить" определенное количество записей в сочетании с "предельным" количеством записей на выборку. Оба значения пропуска и ограничения - +ve.

У меня есть список в ST, который должен иметь самую последнюю запись внизу. Когда пользователь вводит запись, запись должна быть добавлена к нижней. Когда пользователь прокручивается вверх, список должен извлекать предыдущие записи, используя разбиение на страницы.

1-й вопрос: чтобы показать самое последнее сообщение внизу, я сортирую список на ST в порядке возрастания созданной метки времени - есть ли способ достичь этого без сортировки?

Второй вопрос: у меня есть пользовательский плагин (небольшой вариант плагина подкачки списка), который извлекает предыдущие записи при прокрутке вверх, но даже если я динамически устанавливаю scrollToTop в false, как только магазин загружается, список продолжает прокручиваться до верхний (не с анимацией). Как я могу избежать этого?

Любая помощь высоко ценится! Благодарю!

Вот мой код плагина:

/**
* Adds a Load More button at the bottom of the list. When the user presses this button,
* the next page of data will be loaded into the store and appended to the List.
*
* By specifying '{@link #autoPaging}: true', an 'infinite scroll' effect can be achieved,
* i.e., the next page of content will load automatically when the user scrolls to the
* bottom of the list.
*
* ## Example
*
* Ext.create('Ext.dataview.List', {
*
* store: Ext.create('TweetStore'),
*
* plugins: [
* {
* xclass: 'Ext.plugin.ListPaging',
* autoPaging: true
* }
* ],
*
* itemTpl: [
* '<img src="{profile_image_url}" />',
* '<div class="tweet">{text}</div>'
* ]
* });
*/
Ext.define('MyApp.ux.plugin.ListReversePaging', {
extend: 'Ext.Component',
alias: 'plugin.listreversepaging',
config: {
/**
* @cfg {Boolean} autoPaging
* True to automatically load the next page when you scroll to the bottom of the list.
*/
autoPaging: false,
/**
* @cfg {String} loadMoreText The text used as the label of the Load More button.
*/
loadMoreText: '',
/**
* @cfg {String} noMoreRecordsText The text used as the label of the Load More button when the Store's
* {@link Ext.data.Store#totalCount totalCount} indicates that all of the records available on the server are
* already loaded
*/
noMoreRecordsText: '',
/**
* @private
* @cfg {String} loadTpl The template used to render the load more text
*/
loadTpl: [
'<div class="{cssPrefix}loading-spinner" style="font-size: 180%; margin: 10px auto;">',
'<span class="{cssPrefix}loading-top"></span>',
'<span class="{cssPrefix}loading-right"></span>',
'<span class="{cssPrefix}loading-bottom"></span>',
'<span class="{cssPrefix}loading-left"></span>',
'</div>',
'<div class="{cssPrefix}list-paging-msg">{message}</div>'
].join(''),
/**
* @cfg {Object} loadMoreCmp
* @private
*/
loadMoreCmp: {
xtype: 'component',
baseCls: Ext.baseCSSPrefix + 'list-paging',
scrollDock: 'top',
hidden: true
},
/**
* @private
* @cfg {Boolean} loadMoreCmpAdded Indicates whether or not the load more component has been added to the List
* yet.
*/
loadMoreCmpAdded: false,
/**
* @private
* @cfg {String} loadingCls The CSS class that is added to the {@link #loadMoreCmp} while the Store is loading
*/
loadingCls: Ext.baseCSSPrefix + 'loading',
/**
* @private
* @cfg {Ext.List} list Local reference to the List this plugin is bound to
*/
list: null,
/**
* @private
* @cfg {Ext.scroll.Scroller} scroller Local reference to the List Scroller
*/
scroller: null,
/**
* @private
* @cfg {Boolean} loading True if the plugin has initiated a Store load that has not yet completed
*/
loading: false
},
/**
* @private
* Sets up all of the references the plugin needs
*/
init: function(list) {
var scroller = list.getScrollable().
getScroller(),
store = list.getStore();

this.setList(list);
this.setScroller(scroller);
this.bindStore(list.getStore());

this.addLoadMoreCmp();

// The List Store could change at any time so make sure we are informed when that happens
list.updateStore = Ext.Function.createInterceptor(list.updateStore, this.bindStore, this);

if (this.getAutoPaging()) {
scroller.on({
scrollend: this.onScrollEnd,
scope: this
});
}
},
/**
* @private
*/
bindStore: function(newStore, oldStore) {
if (oldStore) {
oldStore.un({
beforeload: this.onStoreBeforeLoad,
load: this.onStoreLoad,
filter: this.onFilter,
scope: this
});
}

if (newStore) {
newStore.on({
beforeload: this.onStoreBeforeLoad,
load: this.onStoreLoad,
filter: this.onFilter,
scope: this
});
}
},
/**
* @private
* Removes the List/DataView loading mask because we show our own in the plugin. The logic here disables the
* loading mask immediately if the store is autoloading. If it not autoloading, allow the mask to show the first
* time the Store loads, then disable it and use the plugin loading spinner.
* @param {Ext.data.Store} store The store that is bound to the DataView
*/
disableDataViewMask: function() {
var list = this.getList();
this._listMask = list.getLoadingText();

list.setLoadingText(null);
},
enableDataViewMask: function() {
if (this._listMask) {
var list = this.getList();
list.setLoadingText(this._listMask);
delete this._listMask;
}
},
/**
* @private
*/
applyLoadTpl: function(config) {
return (Ext.isObject(config) && config.isTemplate) ? config : new Ext.XTemplate(config);
},
/**
* @private
*/
applyLoadMoreCmp: function(config) {
config = Ext.merge(config, {
html: this.getLoadTpl().
apply({
cssPrefix: Ext.baseCSSPrefix,
message: this.getLoadMoreText()
}),
scrollDock: 'bottom',
listeners: {
tap: {
fn: this.loadNextPage,
scope: this,
element: 'element'
}
}
});

return Ext.factory(config, Ext.Component, this.getLoadMoreCmp());
},
/**
* @private
* If we're using autoPaging and detect that the user has scrolled to the bottom, kick off loading of the next page
*/
onScrollEnd: function(scroller, x, y) {

var list = this.getList();

if (!this.getLoading() && y <= 50) {

this.currentScrollToTopOnRefresh = list.getScrollToTopOnRefresh();
list.setScrollToTopOnRefresh(false);

this.loadNextPage();
}
},
/**
* @private
* Makes sure we add/remove the loading CSS class while the Store is loading
*/
updateLoading: function(isLoading) {
var loadMoreCmp = this.getLoadMoreCmp(),
loadMoreCls = this.getLoadingCls();

if (isLoading) {
loadMoreCmp.addCls(loadMoreCls);
} else {
loadMoreCmp.removeCls(loadMoreCls);
}
},
/**
* @private
* If the Store is just about to load but it currently empty, we hide the load more button because this is
* usually an outcome of setting a new Store on the List so we don't want the load more button to flash while
* the new Store loads
*/
onStoreBeforeLoad: function(store) {
if (store.getCount() === 0) {
this.getLoadMoreCmp().
hide();
}
},
/**
* @private
*/
onStoreLoad: function(store) {
var loadCmp = this.getLoadMoreCmp(),
template = this.getLoadTpl(),
message = this.storeFullyLoaded() ? this.getNoMoreRecordsText() : this.getLoadMoreText();

if (store.getCount()) {
loadCmp.show();
}
this.setLoading(false);

//if we've reached the end of the data set, switch to the noMoreRecordsText
loadCmp.setHtml(template.apply({
cssPrefix: Ext.baseCSSPrefix,
message: message
}));

if (this.currentScrollToTopOnRefresh !== undefined) {

this.getList().
setScrollToTopOnRefresh(false);
delete this.currentScrollToTopOnRefresh;
}

this.enableDataViewMask();
},
onFilter: function(store) {
if (store.getCount() === 0) {
this.getLoadMoreCmp().
hide();
} else {
this.getLoadMoreCmp().
show();
}
},
/**
* @private
* Because the attached List inner list element is rendered after our init function is called,
* we need to dynamically add the loadMoreCmp later. This does this once and caches the result.
*/
addLoadMoreCmp: function() {
var list = this.getList(),
cmp = this.getLoadMoreCmp();

if (!this.getLoadMoreCmpAdded()) {
list.add(cmp);

/**
* @event loadmorecmpadded Fired when the Load More component is added to the list. Fires on the List.
* @param {Ext.plugin.ListPaging} this The list paging plugin
* @param {Ext.List} list The list
*/
list.fireEvent('loadmorecmpadded', this, list);
this.setLoadMoreCmpAdded(true);
}

return cmp;
},
/**
* @private
* Returns true if the Store is detected as being fully loaded, or the server did not return a total count, which
* means we're in 'infinite' mode
* @return {Boolean}
*/
storeFullyLoaded: function() {
var store = this.getList().
getStore(),
total = store.getTotalCount();

return total !== null ? store.getTotalCount() <= (store.currentPage * store.getPageSize()) : false;
},
/**
* @private
*/
loadNextPage: function() {
var me = this;
if (!me.storeFullyLoaded()) {
me.disableDataViewMask();
me.setLoading(true);
me.getList().
getStore().
nextPage({addRecords: true});
}
}
});

спросил(а) 2014-08-27T09:15:00+04:00 5 лет, 11 месяцев назад
1
Решение
88

На вопрос 1

Конечно: используйте вставку (индекс, записи) http://docs.sencha.com/touch/2.3.1/#!/api/Ext.data.Store-method-insert

вы можете увидеть, сколько предметов вам нужно знать индекс, который вы должны использовать для вставки:

var totalCount = myStore.getTotalCount();  //lets say there are 10 elements
var recordMsg = {title : "User message", content, "Hello"}; //create new model /record

myStore.insert(totalCount, recordMsg); // so since there are 10 elements indexes 0 -9 are already taken, lets use index 10 and put it at the end

ответил(а) 2014-09-01T19:36:00+04:00 5 лет, 11 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема