Facebook like infinite scrolling - extjs

Will it be possible to implement facebook or linked in like infinite scrolling using EXT-JS API. I am aware of infinite grid although my requirement is to scroll panels infinitely just like facebook or linked in allows us. As of now I am working on EXT version 5.
Any link/white paper will greatly be appreciated.
Thanks in advance
Samir

You can use a dataview with a store tied to it to load the initial data in the wall. Then, in a controller add a listener to the scroll event and check when the scroll has reached the end.
I previously was creating a reddit app with that exact functionality though it was never completed/fully vetted. Here is a snippet of the scroll callback, basically I kicked off an ajax request and then load the returned data to the end of the current store's data:
mainPanelRendered: function () {
var p = Ext.ComponentQuery.query('yourDataView')[0];
var s = p.getStore();
//check on scroll if we've reached the end of the dataview
p.getTargetEl().on('scroll', function (e, t) {
var height = p.getTargetEl().getHeight();
if (height + t.scrollTop >= t.scrollHeight) { //Fire method to load more data to the store.
p.setLoading(true);
Ext.data.JsonP.request({
callbackKey:'jsonp',
url: s.proxy.url,
params: {
'count': 25,
'after': p.after
},
headers: { 'Content-type': 'text/json; charset=utf-8', 'Accepts': 'text/json' },
reader: {
type: 'json',
root: 'data.children',
successProperty: 'success'
},
success: function (response) {
p.after = response.data.after;
//now that you have more data add it to the store
Ext.each(response.data.children, function (article) {
var data = article.data;
try{
s.add({
id: data.id,
domain: data.domain,
subreddit: data.subreddit,
author: data.author,
over_18: data.over_18,
thumbnail: data.thumbnail,
subreddit_id: data.subreddit_id,
downs: data.downs,
ups: data.ups,
permalink: data.permalink,
name: data.name,
url: data.url,
title: data.title,
num_comments: data.num_comments,
score: data.score
});
} catch (ex) {
//do nothing the item already existed
}
//s.add(item);
//newItems[i] = item;
//i++;
});
p.setLoading(false);
//p.after = p.response.data.after;
}
});
}
});
},
And here is a link to my not-so-complete app's source. Again, it certainly isn't fully vetted but should give you an idea how you could add an infinite scroll. Checkout the mainPanel in the view and the render event in the controller.

Related

Select2 custom data fetch when user starts typing in search bar. (BackboneJS / Marionette collection) SELECT2

I am using SELECT2 in BackboneJS/Marionette. Right now following is flow:
Current:
From parent, call FETCH method of COLLECTION. When fetch is completed then send this COLLECTION to a new VIEW and display drop down (SELECT2)
New Requirement:
Now need to convert this data fetch at run-time. When user types in search bar of SELECT2, ajax call should be made and returned data needs to be converted to Marionette collection and then rendered in drop-down.
For this, i tried to implement this example.
Now problem is that data is fetched (visible in network tab), but drop-down remains empty (and there is no error/exception):
Added following code in _SELECTOR.prototype.settings.extend
ajax: {
url: API_PATH + "testingvalues2",
dataType: 'json',
delay: 1000,
minimumInputLength: 1,
cache: true,
data: function (params) {
var query = {
filter: params.term
};
console.log("query: ", query);
return query;
},
processResults: function (data) {
console.log("data : ", data);
console.log("this>>", this);
let newCollection = new DropdownDataCollection();
for(let dataItem of data){
let item = new DropdownValueEntity (dataItem);
newCollection.add(item);
}
return {results : newCollection};
}
},

Properties not changing on the DOM after a GET request

I am working on a component to render user details. The details are fetched from an API request and properties are updated but these changes are not reflected on the DOM.
The company I work for is still using Polymer 1.2 and I am having difficulty finding and understanding the documentation. Do I need to make the get request from the parent component or is it possible to do this directly inside the component? There is something fundamental I am not grasping about this and wondering if someone could shed some light on it for me.
Thank you.
Snippet from the template:
<p>{{i18n.GLOBAL_USERNAME}} - [[username]]</p>
<p>{{i18n.GLOBAL_FIRSTNAME}} - [[firstname]]</p>
<p>{{i18n.GLOBAL_LASTNAME}} - [[lastname]]</p>
<p>{{i18n.GLOBAL_EMAIL}} - [[email]]</p>
<p>{{i18n.GLOBAL_NUMBER}} - [[number]]</p>
Snippet from the polymer functions:
Polymer({
is: 'my-component',
properties: {
username: {
type: String,
value: "n/a",
},
firstname: {
type: String,
value: "n/a"
},
lastname: {
type: String,
value: "n/a"
},
email: {
type: String,
value: "n/a"
},
number: {
type: String,
value: "n/a"
},
},
ready: function () {
var user = app.auth.hasSession()
if (user !== null) {
app.getUserInfo(user.user_id, this._getUserSuccessful, this._getUserFail);
}
},
_getUserSuccessful: function (res) {
this.username = res.user.user_id
this.firstname = res.user.firstname
this.lastname = res.user.lastname
this.email = res.user.email
this.number = res.user.phone_number
console.log("got user details")
},
_getUserFail: function () {
console.log("failed to get user details")
},
});
You need to use Polymer setter methods instead of plain assignment.
Here's an example:
_getUserSuccessful: function (res) {
this.set('username', res.user.user_id)
this.set('firstname', res.user.firstname)
this.set('lastname', res.user.lastname)
this.set('email', res.user.email)
this.set('number', res.user.number)
console.log("got user details")
},
Using setter and/or array mutator methods is required for data-bound properties otherwise Polymer can't know that something has changed in order to update the bindings.
I'd really suggest you read the whole Data system concepts article before moving forward with doing any kind of work with Polymer 1.x.

Combobox inside Extjs editor grid panel while populating is invisible sometimes

Hi all I am using Extjs 3.4 my problem is I have one editor grid panel
and inside panel I have one department combobox. So, in first page I
have search grid and on click of grid I am coming to this page and on
load using ajax I am populating combobox value in grid panel. But sometimes
values are not coming, means it is invisible and only after clicking on that
combobox it is appearing. Can some body explain what is the problem.
Thanks in advance, I hope will get reply soon.
While populating I am calling one ajax which is populating values in grid but
there is no issue with other columns, only with combobox it is invisible sometimes
Ext.util.Format.comboRenderer = function(Departmentscombo){
return function(value){
var record = combo.findRecord(combo.valueField || combo.displayField, value);
return record ? record.get(combo.displayField) : combo.valueNotFoundText;
}
}
Ext.grid.ComboColumn = Ext.extend(Ext.grid.Column, {
constructor: function(cfg){
Ext.grid.ComboColumn.superclass.constructor.call(this, cfg);
this.renderer = Ext.util.Format.comboRenderer(this.editor.field ?
this.editor.field : this.editor);
}
});
Ext.apply(Ext.grid.Column.types, {
combocolumn: Ext.grid.ComboColumn
});
var DepartmentsJReader = new Ext.data.JsonReader
({ root: 'data', id: 'mastercode' },
[{ name: 'mastercode' }, { name: 'description'}]);
Departments_store = new Ext.data.Store
({
proxy: new Ext.data.HttpProxy(
{ url: '', method: 'GET' }),
reader: DepartmentsJReader, autoLoad: true,
listeners:
{
load: function () {
var rec = new Departments_store.recordType({ mastercode:'-', description: '-' });
rec.commit();
Departments_store.insert(0, rec);
Departments_store.commitChanges();
}
}
});

Handling Subsidiary Views in Backbone.js

I have a basic Backbone application which obtain an array of JSON objects from a remote service and displays them: all good so far. However, each JSON object has an array of tags and I want to display the tags in a separate area of the webpage.
My question is: what is the most Backbone-friendly way of doing this? I could parse the existing data again in a second view, which is cleaner but takes up more computation (processing the entire array twice).
An alternative is gathering up the tag information in the primary view as it is working through the array and then passing it along to the subsidiary view, but then I'm linking the views together.
Finally, I'd like to filter based on those tags (so the tags will become toggle buttons and turning those buttons on/off will filter the information in the primary view); does this make any difference to how this should be laid out?
Bonus points for code snippets.
Hm. I'm not sure if this is the Backbone-friendly way, but I'll put the logic to retrieve a list of tags (I think that's what you meant by "parse") in the collection.
Both the main view and the subview will "listen" to the same collection, and the subview will just call collection.getTags() to get a list of tags it needs.
// Model that represents the list data
var ListDataModel = Backbone.Model.extend({
defaults: function() {
return {
name: null,
tags: []
};
}
});
// Collection of list data
var ListDataCollection = Backbone.Collection.extend({
model: ListDataModel,
initialize: function() {
var me = this;
// Expires tag collection on reset/change
this.on('reset', this.expireTagCache, this);
this.on('change', this.expireTagCache, this);
},
/**
* Expires tag cache
* #private
*/
expireTagCache: function() {
this._cachedTags = null;
},
/**
* Retrieves an array of tags in collection
*
* #return {Array}
*/
getTags: function() {
if (this._cachedTags === null) {
this._cachedTags = _.union.apply(this, this.pluck('tags'));
}
return this._cachedTags;
},
sync: function(method, model, options) {
if (method === 'read') {
var me = this;
// Make an XHR request to get data for this demo
Backbone.ajax({
url: '/echo/json/',
method: 'POST',
data: {
// Feed mock data into JSFiddle's mock XHR response
json: JSON.stringify([
{ id: 1, name: 'one', tags: [ 'number', 'first', 'odd' ] },
{ id: 2, name: 'two', tags: [ 'number', 'even' ] },
{ id: 3, name: 'a', tags: [ 'alphabet', 'first' ] }
]),
},
success: function(resp) {
options.success(me, resp, options);
},
error: function() {
if (options.error) {
options.error();
}
}
});
}
else {
// Call the default sync method for other sync method
Backbone.Collection.prototype.sync.apply(this, arguments);
}
}
});
var listColl = new ListDataCollection();
listColl.fetch({
success: function() {
console.log(listColl.getTags());
}
});
I guess two reasons for handling this in the collection:
It keeps the View code cleaner (This is given that we are not doing very complex logic in the tag extraction - It's just a simple _.pluck() and _.union().
It has 0 business logic involved - It can arguably belong to the data layer.
To address the performance issue:
It does go through the collection twice - However, if the amont of data you are consuming is too much for the client to process even in this case, you may want to consider asking the Backend to provide an API endpoint for this. (Even 500 pieces of data with a total of 1000 tags shouldn't bee too much for a somewhat modern browser to handle nowadays.)
Hmm. Does this help?
JSFiddle to go with this with the collection and the model: http://jsfiddle.net/dashk/G8LaB/ (And, a log statement to demonstrate the result of .getTags()).

Adding new HighChart Series

At this code javascrip give an error
$.each(JSON, function(i, array) {
chart.series[i].name = array.teamName;
chart.series[i].setData(array.teamPower, true);
});
I must define the chart.series[i] because it say "Cannot set property 'name' of undefined"
but i can't find a way in order to do this.
Because it fonction runs with requestData so it came after chart determine with options
function showGraph() {
chart = new Highcharts.Chart(option);
}
chart: {
renderTo: 'graphicShow',
type: 'spline',
events: {
load: requestData
}
}
...in option...
title: {
text: 'Power %'
},
series: []
...
You need to looka at the "Methods and Properties" part of the API. See http://api.highcharts.com/highcharts#Chart (There is an jsFiddle on the documentation page as well).
var chart = new Highcharts.Chart(options);
chart.addSeries({
name: array.teamName,
data: array.teamPowher
});
If you are going to add several series you should set the redraw flag to false and then call redraw manually after as that will be much faster.
var chart = new Highcharts.Chart(options);
chart.addSeries({
name: array.teamName,
data: array.teamPower
}, false);
chart.addSeries({
name: array.teamName,
data: array.teamPower
}, false);
chart.redraw();
You too can specify as second option of addSeries a boolean value, that indicates if it redraws or not

Resources