Webix Treetable with pagination and grouping - webix

I'm using a webix treetable with data loading from a server url with pagination.
Server url loads 100 records per page with total_count as say 1000.
It works fine so far.
But if I apply grouping on a column, it's throwing error. When I debug I understood that it's failing because it's trying to process 1000 records (based on the total_count) where as there are only 100 records loaded so far and throwing an error.
Is it possible to have grouping + remote pagination together on webix treetable.
Please check the sample code I'm using -
webix.ready(function () {
var gridColumns = [{
// ...
}];
var grid = webix.ui({
container: "testA",
view: "treetable",
columns: gridColumns,
url: "server-url.php"
scheme: {
$group: gridColumns[0].id
},
datafetch: 100,
pager: {
container: "paging_here",// the container where the pager controls will be placed into
size: 100, // the number of records per a page
group: 5 // the number of pages in the pager
}
});
});
and the html is
<div id="testA" style='width:1200px; height:600px;'></div>
<div id="paging_here"></div>

It will not work, unfortunately.
The grouping requires that all data is available on the client side, which means it doesn't compatible with dynamic loading.
If you have up to few thousands of records, you an try to load all data at once. Except the extra bandwidth, it will not have a negative impact on the performance.

Related

Ag grid react: How to specify start page, pagination

I'd like to know id there is a way to open an ag-grid on the last page upon start. The page size is 10000 and the extra rows should go in the first page, not the last. (So the last page and everything else except for the first page should have 10000 rows)
I've done some research online and didn't really find what I was looking for. I tried implementing the getRows method below but the results are the same.
getRows (params) {
// Use startRow and endRow for sending pagination to Backend
params.startPage = (this.state.fileNames.length / 1000);
params.endPage = 1;
this.apiService().subscribe(response => {
params.successCallback(
response.data, response.totalRecords
);
})
}

Antd Table Pagination show No Data when moved to second page

I am using Antd Table component, I have bind data by below code. The first page is load data correctly, but when I moved to the second page, it is showing me 'No Data'. I have debugged code and tried to figure it out issue and found that reached data in render state as well but don't know why not bind it. It's work fond at localhost but when i deployed to server, it couldn't work.
Code:
enter image description here
Screenshot::
enter image description here
For people in the future who might have this problem (I also had the problem and solved it):
You probably have the current pageindex and pagesize stored in Redux.
If you have for instance:
30 results in total
a page size of 10
and you are on page 3
Now you change the page size to 100 (and of course you will only have 1 page) then your redux pageindex is still 3 and you try to access page 3 although only one page exists.
This leads to this error.
Solution:
const pagination = {
position: ['bottomCenter'],
showSizeChanger: true,
showQuickJumper: true,
onChange: (page) => {
dispatchFns.setConfig('currentPage', page);
},
onShowSizeChange: (_, pPageSize) => {
dispatchFns.setConfig('currentPage', 1); // this is the necessary line to fix the bug
dispatchFns.setConfig('pageSize', pPageSize);
},
total: itemsToShow.length,
current: currentPage,
pageSize,
};
// currentPage comes from Redux
// pageSize comes from Redux
Its resolved!
I have added current (current:pagination.current) in pagination option in antd table as below
<Table
size={'small'}
scroll={{ x: 370 }}
rowKey={record => record.template_id}
columns={columns}
dataSource={roleTemplateData}
pagination={{ pageSize: pagination.pageSize, pageSizeOptions: pageSizeOptions, showSizeChanger: true, total: pagination.total, position: position, current:pagination.current }}
loading={loading}
onChange={this.handleTableChange}
/>
Thanks.

Would it be possible to do lazy loading in Relay?

I have a Parent component which contains many Child components as an array. Each child component contains a huge amount of data. So, I decided to not load all of them when Parent get loaded. The data fetched from Parent container is as following:
{
...
childs: [childId1, childId2, ...] // Array of child id
...
}
Then, I would like to send one request per child by passing the child's id to back-end apis. Each child will be show up on the UI whenever its data get back, otherwise, a spinner icon is displayed for indicating the loading data.
Would it be possible to achieve this in Relay?
UPDATED:
Here is an example of the option 1:
Child container:
export default Relay.createContainer(Child, {
initialVariables: {
id: null,
hasQuery: false
},
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
child(id: $id) #include(if: $hasQuery) {
...
}
}
`,
},
});
Child component:
const Child = React.createClass({
componentWillMount() {
ChildContainer.setVariables({ id: this.props.childId, hasQuery: true });
}
});
Parent container:
export default Relay.createContainer(Parent, {
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
childIds // Return an array of child's id
Child.getFragment('viewer')
}
`,
},
});
Parent component:
const Parent = React.createClass({
render() {
this.props.viewer.childIds.map(childId => {
<Child childId={childId} />
});
}
});
The problem is that when each Child got rendered, it fetched its data and replaced the last Child data with its own data. For example, if childIds = [1, 2, 3], it displayed data of 3 three times on the screen; 3 3 3
There are two typical patterns for delayed data fetching in open-source Relay:
Use #include or #skip directives where the condition is initially set to false. After the UI loads, or in response to user action, set the condition to true (e.g. with setVariables).
Use nested <Relay.Renderer> components. The top-level <RelayRenderer> would fetch the minimum "required" data in one round trip and then display it, which would render additional <RelayRenderer>s that would fetch more data.
The second option seems best-suited to your use case: the top-level renderer would fetch the list of IDs only. Then it would render a list of UI components, each of which fetched more data about its ID. List items would render as their data resolves.
One potential downside of this approach is that the data for all the items will be fetched in parallel; the first item in the list won't necessarily be the first one to get its data and render. To mitigate this an application would have to maintain greater control of the ordering of fetches; Relay accommodates this via an injectable network layer. For example, you could batch requests to the server and/or ensure ordering (for example by intentionally delaying resolving responses of "later" requests until previous queries have completed). You might check out the community-driven react-relay-network-layer which implements some of these ideas and supports pluggable middleware to help achieve the rest.

passing backbone collection to view

I'm just starting out with backbone / grails and i've been struggling to figure out how to get everything to work.
I'm building a pricing configurator where a user selects a product type from radio group A and radio group B containing the quantity / pricing / discount data will do an ajax call to the backend for updated pricing data. I do not want to expose my pricing algorithm to the front end, so I was thinking I would use backbone to handle my ajax request / template.
I do not want to fully rely on js to create my UI, so on the initial page load, I'll build the gsp view with grails. Only problem I've noticed was my gsp view was being replaced by my handlebars template on initial page load. I guess this is fine, except it does two identical queries which isn't optimal.
Anyhow my code that does not seem to be working.
<script id="priceTemplate" type="text/x-handlebars-template">
<tr>
<td><input type="radio" value="" name="quantity">{{quantity}}</td>
<td class="price"><span>{{price}}</span></td>
<td class="discount"><span>{{discount}}</span></td>
</tr>
</script>
<asset:javascript src="bb_product/config.js"/>
<script>
var prices = new models.PriceList([],{productId:${productInstance.id}});
var priceView = new PriceView({collection: prices});
prices.fetch();
</script>
Models
var models = {};
models.PriceModel = Backbone.Model.extend({
//Is the model automatically populated from the collections json response?
})
models.PriceList = Backbone.Collection.extend({
initialize: function(models, options) {
this.productId = options.productId;
},
model: models.PriceModel,
url: function() {
return '../product/pricing/' + this.productId + '.json'
}
});
View
var PriceView = Backbone.View.extend({
el: '#product-quantities',
template: Handlebars.compile($("#priceTemplate").html()),
initialize: function(){
this.render();
},
render: function() {
console.log('collection ' + this.collection.toJSON()) //comes back empty
this.$el.html( this.template(this.collection.toJSON()));
}
});
json returned from url
[{"id":1,"quantity":10,"price":"10","discount":"10"},{"id":2,"quantity":50,"price":"20","discount"
:"10"}]
To initially get this up and working, what am I missing to display all items in the json object?
I've also see this code around, not sure what it does this.listenTo(this.collection, 'reset', this.render);
The reason you don't see any items is that the items aren't actually in the collection until after the view is rendered. Look at these two lines of code:
var priceView = new PriceView({collection: prices});
prices.fetch();
The first line renders the view (since you're calling render from within initialize). However, at that time, the prices collection is empty. Then, the second line fetches the data from the server and loads it into the collection; but by that time, the view has been rendered.
That last line of code you posted is the key to fixing this:
this.listenTo(this.collection, 'reset', this.render);
Usually, you'll put this inside the initialize function in your view class. What this does is "listen" to the collection instance, and when the reset event occurs, it will call the this.render function. (Of course, the method this.listenTo can "listen" to other objects for other events; see more details in the Backbone documentation).
If you add that line to the view's initialize function, the view will re-render whenever a "reset" event happens on the collection.
HOWEVER, by default, the "reset" event happens when all the models in the collection are replaced with another set of models, and this doesn't happen by default when you call a collection's fetch method (instead, the collection will try to "smart-update"). To force a reset of the collection when using fetch, pass {reset: true} as a parameter:
prices.fetch({reset: true});

Can not select row in subgrid : Jqgrid

I am using jqgrid, and added one subgrid inside it, which looks like as below,
As you can see,
Rows with columns having 11 and 13 are main grid rows
And every row has subgrid having interest,
The Add Record element shows Add Pop up for Subgrid
Here is the code for subgrid looks like,
subGridRowExpanded: function(subgrid_id, row_id) {
var subgrid_table_id, pager_id;
subgrid_table_id = subgrid_id+"_t";
pager_id = "p_"+subgrid_table_id;
$("#"+subgrid_id).html("<table id='"+subgrid_table_id+"' class='scroll'></table><div id='"+pager_id+"' class='scroll'></div>");
jQuery("#"+subgrid_table_id).jqGrid({
url:"shops?q=2&ShopID="+row_id,
datatype: "xml",
colNames: ['Interest'],
colModel: [
//{name:"Id",index:"ShopID",width:80,editable:false,editoptions:{readonly:false,size:40}}, //Shop ID not required
{name:"id",index:"id",editable:true,edittype:"select",editoptions:{dataUrl:'shops?q=3&ShopID='+row_id},editrules:{required:true}}
],
rowNum:10,
pager: pager_id,
width: '100%',
height: '100%',
scrollOffset: 0,
sortname: 'num',
sortorder: "asc",
height: '100%',
editurl:'shops?q=5&ShopID='+row_id
});
jQuery("#"+subgrid_table_id).jqGrid('navGrid',"#"+pager_id,{edit:false,add:true,del:true})
},
subGridRowColapsed: function(subgrid_id, row_id) {
// this function is called before removing the data
//var subgrid_table_id;
//subgrid_table_id = subgrid_id+"_t";
//jQuery("#"+subgrid_table_id).remove();
}
Problem is , when there are more than one element in subgrid, i can select that (I use latest version of Chrome) but when there is only single element in subgrid surprisingly I can select it ( if you notice the color difference please see subgrid element 'Gifts' -selected below row 13 ) and once select that 'Gifts' can be deleted.
UPDATE:
In firefox and IE , only first row gets selected from subgrid
Is there something wrong in the code ? why can't i select single element when there are more than one elements in subgrid ?
Appreciate your time, thanks
I suppose that you have problem with id duplicates. HTML don't allow to use id attributes on the same HTML pages with the same values. The values of all id attributes must be unique. I recommend you to verify that you have the problem by usage of Developer Tools of Chrome/IE or using Firebug. You need just examine the id attributes which you have now on <tr> elements of grid and subgrids.
On the other side all rows (all <tr> elements) of jqGrid become an id attribute assigned. Typically you have to fill id in the server side in the response of url. The problem is that one use typically the values from id from the database, but you have typically unique id only over one table of the database and not over all tables on the database. So you can easy have the scenario where multiple jqGrids (or grid with subrird) get rows with id duplicates.
The most easy way to fix the problem is to use idPrefix option which was introduced in jqGrid after my suggestion. The main advantage is that you can continue to use the original id values which you have in the database and use id attributes in jqGrid which will be unique because of building id attributes from the id values returned from the server, but with the usage of prefixes. In the answer. So I recommend you to use different idPrefixes for all subgrids. For example you can use idPrefix: 's' + row_id + '_' in subgrid (see the answer and this one).

Resources