how it works pagination in prestashop? - pagination

I have done some modification and now need to build my own pagination.
So i know prestashop have his own so how can i use them?
I was trying to use in classes/controller/FrontController.php
Use function:
public function pagination($nbProducts = 10)
{....
But can't understand well where and how is formed a pagination itself... i think my php knowledgment is low so i need some help if somebody get understand how is pagination of Prestashop works.

Front Controller assign products and the number of products in smarty variables for the page you want to see.
Here the example with BestSales Page in BestSalesController :
$nbProducts = (int)ProductSale::getNbSales();
$bestSales = ProductSale::getBestSales($this->context->language->id, $this->p - 1, $this->n, $this->orderBy, $this->orderWay);
....
// then assign it to smarty
$this->context->smarty->assign(array(
'nbProducts' => $nbProducts,
'products' => $bestSales
));
There is nothing special or custom things you can do in Front Controller.
If you want to make a custom pagination, take a look at the blocklayered module.
For example, in modules/blocklayered/blocklayered.php at ajaxCall() function, you can specify custom choices for 'the number of products by page' by editing this line :
$nArray = (int)Configuration::get('PS_PRODUCTS_PER_PAGE') != 10 ? array((int)Configuration::get('PS_PRODUCTS_PER_PAGE'), 10, 20, 50) : array(10, 20, 50);
This line display 10, 20, 50 and default number of products per page specified in Back-Office/Preferences/Products but you can change it as your wish, example :
$nArray = array(10, 20, 30, 40, 50, 60);
If you want to make customizations, you have to made them in this module, but it wouldn't be simple (the file is hitting 4200 lines, so good luck !).

Related

SAP UI5 to Implement "go to" specific page on the table

I am new to SAP UI5 development. Currently the table is using "growing" and "growingThreshhold", then users can click more to see data of next page. Since we have thousands of data in that table, it takes user time to click more and more again to load next page data. we try to implement a function, that user can enter the page number then click a button and go to the specific page.
<Table id="genTable" growing="true" growingThreshold="60" fixedLayout="false" selectionChange="onHandleSelectChange"
backgroundDesign="Solid" updateFinished="onHandleGeneratorQueueUpdateFinished">
Expected UI:
I added a bar then UI display is good.
<Bar design="SubHeader">
<contentMiddle>
<Input type="Number" id="pageNumber" width="50px"></Input>
<Button id="goToButton" text="Go to" type="Emphasized" press="onHandleGoTo"></Button>
</contentMiddle>
</Bar>
For the backend logic, I refer to below articles, but still doesn't work.
https://blogs.sap.com/2016/12/14/sapui5-pagination-in-sap.m-table-on-button-click-using-odata-service/
https://sapyard.com/advance-sapui5-19-pagination-in-table-control-with-top-and-skip-query-options/
I tried to use read, the it can get the data back from odata service, but the data can't be refreshed in the table.
oModel.read("/ViewQueueSet", {
urlParameters: {
"$top": top,
"$skip": count
},
filters: [new Filter("RoleCode", FilterOperator.EQ, "G")],
useBatch: true,
success: function (tdata) { //successful Read in the server
var json = new JSONModel();
json.setData(tdata);
that.getView().setModel(json,"sapmodel");
sap.ui.core.BusyIndicator.hide();
},
error: function () {
sap.ui.core.BusyIndicator.hide();
}
});
}
also tried to call bindItems
//that.getView().setModel(json,"sapmodel");
//oTable.setModel(json); //JSON is preferred data format
//oTable.bindItems("/results",that.oGenQueueTemplate);
that.getView().byId("genTable").setModel(json);
that.getView().byId("genTable").bindItems("/results",that.oGenQueueTemplate);
Another approach I tried is to use bindItems, it call send the request to odata service, but it doesn't add the parameter top and skip parameter.
oTable.bindItems({
path: "/ViewQueueSet",
model: "sapmodel",
filters: [new Filter("RoleCode", FilterOperator.EQ, "G")],
template: this.oGenQueueTemplate,
// urlParameters: {
// "$top": top,
// "$skip": count
// },
parameters: {
"$top": top,
"$skip": count
}
});
Anyone has any idea about how to implement this functionality?
before I go into detail, please consider using other controls and/or ux patterns. imagine having thousands or millions of elements in backend and user equests to scroll to page 9292929 => for a responsive table (sap.m.Table) you would need to load all elements up to that page. Maybe filtering or some completely different approach could be tha right one.
The correct way to do this is by getting the listbinding and ask it to load more elements. how to ask the binding, may depend on the type of binding as well.
oTable = ... // get a reference on table
oItemsBinding = oTable.getBinding("items");
oItemsBinding.getLength() // will give you total number of elements
oItemsBinding.isLengthFinal() // will tell you if the length is final
oItemsBinding.getCurrentContexts() // will give you array of all loaded contexts.
now a few words to length and the length being final. If you have a binding implementation that knows the total number of objects (e.g. json - since it loads all elements to client, or OData, if cont is implemented in backend) then getLength will tell you the total number of objects.
if the backend doesnt have the count feature implemented, the length becomes final once you reach the end of the list (backend gives you less elements than you require - e.g. top=10,skip=90 returns 10 elements => length 100, not final; top=10,skip=100 returns 4 elements => length=104 becomes final)
Now, you can have a look at various binding implementations. But be aware that there is a lot to consider (direction of growing - upwards/downwards), at least you dont need to think about filtering/sorting - as this is part of the binding.
There is a nice (private) feature in sap.m.Table (or in sap.m.ListBase, to be more precise), which is called GrowingEnablement. you can use it like this:
// dont forget if _oGrowingDelagate is not undefined or similar
oTable._oGrowingDelegate.requestNewPage()
this will load one more page => you could start from reading the implementation of this method if you want to load several pages in one go.
you could also do a simple trick:
// assume you have 20 elements per page (default)
// and want to get to 7th page (elements 121 - 140)
// ckecks for 7th page exists and 7th page not yet loaded are omitted
oTable.setGrowingThreshold(70) // half of 140, so following load will load second page => 71 to 140
oTable._oGrowingDelegate.requestNewPage() // this will load the second page 71 - 140
// once loading is finished (take care of asynchronity)
oItemsBinding.attachEventOnce("dataReceived", function(oEvent){
// reset the growing threshold to 20
oTable.setGrowingThreshold(20)
// scroll to first element of 7th page (index 120, since count starts from 0)
oTable.scrollToInex(120)
})

pdfkit nodejs, one element per page from page 2

Im using pdfkit to generate pdf invoice.
When all my content fit in one page I have no issue.
However when it doesn't fit and need an extra page, I have a strange behaviour:
Instead of adding the elements in the second page, it only add one line and the rest of the page is blank.
Then on 3rd page I have another element, and the rest it blank, then 4th page, 5th etc.
Here is the code corresponding to this part:
for (let i = 0; i < data.items.length; i++) {
const item = data.items[i];
this.itemPositionY = this.itemPositionY + 20;
if (item.bio) this.containBioProduct = true;
let itemName = item.bio ? `${item.item}*` : item.item;
this.generateTableRow(
doc,
this.itemPositionY,
itemName,
"",
this.formatCurrency(item.itemPriceDf.toFixed(2)),
item.quantity,
this.formatCurrency(item.itemPriceTotalDf.toFixed(2))
);
this.generateHr(doc, this.itemPositionY + 15);
}
Basically I just iterate over an array of products. For each line my Y position has +20.
Thanks for your help.
In case someone has this issue, here is a solution:
Everywhere in the code I know that an extra page could be generated, I add this:
if (this.position > 680) {
doc.addPage();
this.position = 50;
}
It allows you to control the generation of new pages (instead of pdfkit doing it automatically with potential problems)
You just need to track the position from the initialization of "this.position".
In that way, evertime it's superior than an Y position (680 in my case, it's a bit less than a page with pdfkit), you just do "doc.addPage()", which will create another page, and you reinitialize your position to the beginning of the new page.

Dgrid-OnDemandGrid Virtualscrolling

I am using Dgrid OndemandGrid with Jsonrest store.On scrolling,I am taking 40 records from the database.
var grid= new OnDemandGrid({
store: jsonstore,
columns: Layout,
minRowsPerPage : 40,
maxRowsPerPage : 40,
loadingMessage: "Loading data...",
noDataMessage: "No results found."
}, "grid");
On first time ,I am getting the response Header as
Content-Range items=0-39/132
.On further scrolling ,the response Header is
Content-Range items=38-78/132 instead of 40-79/132.
Can someone tell me how to get the response as 40-79/132 , 80-119..etc..
Add queryRowsOverlap: 0 to the object you're passing to the grid constructor.
queryRowsOverlap defaults to 1, and is the reason the queries overlap. This property is intended to counteract issues with dojo/store/Observable "dropping" items at page boundaries, though it isn't a perfect solution.

how to prepopulate target in Primefaces picklist?

How to populate the target in Primefaces picklist? I googled it but i didn't find any example related to this which help my requirement.
I have list of players which is already selected and unassigned. I want to use picklist. Source display the unassigned and target will show the selected one. Admin can make selected player unassigned (target->source) and vice versa.
I think the showcase which zargarf mentioned is quite enough to populate the target. If you look over the constructor of the bean, there are sources populated. In the same way you can populate the targets.
Currently in the constructor is :
//Players
List<Player> source = new ArrayList<Player>();
List<Player> target = new ArrayList<Player>();
source.add(new Player("Messi", 10, "messi.jpg"));
source.add(new Player("Iniesta", 8, "iniesta.jpg"));
source.add(new Player("Villa", 7, "villa.jpg"));
source.add(new Player("Alves", 2, "alves.jpg"));
source.add(new Player("Xavi", 6, "xavi.jpg"));
source.add(new Player("Puyol", 5, "puyol.jpg"));
players = new DualListModel<Player>(source, target);
Do in the same way with the target. target.add(...)
Hope this helps.
Follow the example on the showcase:
http://www.primefaces.org/showcase/ui/picklist.jsf
If you need to only show either target or source control arrows based on user role then you can bind showSourceControls and showTargetControls to a method in the managedbean that returns a string of "true" or "false" depending on the user role
add belwo code
citiesTarget.add("Value1");
citiesTarget.add("value2");

Creating a path in dart:svg

I'm new to using Dart, and I've been trying to port over some javascript code that I had which worked with svg, creating a path with some segments in it, but I'm struggling to understand how the API for it works.
The following code won't run, but it perhaps illustrates what I'd like to do:
Element i = query("#divsvg");
svg.SvgSvgElement s = new svg.SvgSvgElement();
i.append(s);
svg.PathElement p = new svg.PathElement();
p.pathSegList.add(
p.createSvgPathSegArcAbs(200, 200, 50, 50, 180, false, false)
);
s.children.add(p);
However, as far as I understand from the documentation:
createSvgPathSegArcAbs creates an un-parented path segment
pathSegList is final, so you can't add to it after construction
The PathElement constructor doesn't seem to take any arguments
Am I missing something about how Dart works, or something in the documentation for the svg library? I've spent a few hours looking at the docs, googling, and looking at the tests, but I haven't found anything that seems to cover this (the tests seem to create things using HTML code, rather than the API).
Anything that points me in the right direction will be very much appreciated!
Update
I've spent more time looking at the functions, and the 'finality' of the pathSegList shouldn't prevent it from being changed (it's not const), just replaced.
However, various functions like "add" are explicitly implemented with exceptions if you try and call them, while a few functions (like append) are implemented natively.
According to the debugger:
p.pathSegList.append(
p.createSvgPathSegArcAbs(200, 200, 50, 50, 180, false, false)
);
Will append a path segement, but this will not be present in the 'innerHTML' attribute nor in the final page HTML...
I'm starting to think that the svg support is simply not a "finished", and am getting a bit tempted to just port to canvas, and/or WebGL.
I was able to create a path element and add path segments to it using the appendItem method of PathSegList:
var div = query('#container');
var svgElement = new svg.SvgSvgElement();
div.append(svgElement);
path = new svg.PathElement();
svgElement.append(path);
segList = path.pathSegList;
segList.appendItem(path.createSvgPathSegMovetoAbs(50, 50));
segList.appendItem(path.createSvgPathSegArcAbs(200, 200, 50, 50, 180, false, false));
segList.appendItem(path.createSvgPathSegClosePath());

Resources