print reflowed p:dataTable on normal format using p:printer - primefaces

I have the following code
<p:dataTable id="table" reflow="true">
...
</p:dataTable>
<p:commandButton>
<p:printer target="table" />
<p:commandButton>
is there a way to print the table with its normal format even if it is in reflow mode(each row as a stack)?

This is what I end up doing
I created a function to modify jquery print function to format my table as I wanted it before print it
function formatTableBeforePrint() {
$.fn.jqprint = (function() {
var cached_function = $.fn.jqprint;
return function(d) {
$.fn.jqprint.defaults = {
debug : false,
importCSS : true,
printContainer : true,
operaSupport : true
};
var tables = $('.ui-datatable-reflow');
$(".ui-datatable-reflow .ui-datatable-data td .ui-column-title").addClass('noprint');
tables.removeClass('ui-datatable-reflow');
var result = cached_function.apply(this, arguments);
tables.addClass('ui-datatable-reflow');
return result;
};
})();
}
and then called that function from my p:commandButton
<p:commandButton onclick="formatTableBeforePrint()">
<p:printer target="table" />
<p:commandButton>

Related

How do I update the model for a WebGrid using Ajax?

I'm trying to create a WebGrid that allows me to update the data source with Ajax. The data source is assigned a List<> containing a model I created to hold the data. The WebGrid populates correctly and I have no problem sorting using the header of the WebGrid or paging.
The code for the View:
#model IEnumerable<TestDataModel.Models.TestData>
#{
ViewBag.Title = "Test Website";
var grid = new WebGrid(canPage: true, canSort: true, ajaxUpdateContainerId: "grid", ajaxUpdateCallback: "callBack");
grid.Bind(Model, rowCount: 10);
grid.Pager(WebGridPagerModes.All);
#grid.GetHtml(htmlAttributes: new { id = "grid" },
tableStyle: "webgrid-table",
headerStyle: "webgrid-header",
alternatingRowStyle: "webgrid-alternating-row",
rowStyle: "webgrid-row-style",
mode: WebGridPagerModes.All,
firstText: "<< First",
previousText: "< Prev",
nextText: "Next >",
lastText: "Last >>",
columns: grid.Columns("This is a place holder,
I have a lot of columns"
));
}
<div>
<br />
<p>
Page Number: <input type="text" name="pageNumber" id="pageNumber" />
</p>
<p>
<input type="button" name="pageNumberButton" id="pageNumberButton" value="Page" />
</p>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#pageNumberButton").click(function () {
var pageNumber = $("#pageNumber").val();
$.ajax({
url: '#Url.Action("GetData", "Test")?pageNumber=' + pageNumber,
success: function (data) {
$("#grid").html(data);
},
error: function (data) {
alert("Error");
}
})
});
});
</script>
The bottom script tag is the ajax call that I'm trying to use to update the WebGrid. All that the "GetData" does is create a list pulling data from an SQL server and returns Json(testData, JsonRequestBehavior.AllowGet).
Code for Controller:
public ActionResult GetData(string pageNumber)
{
List<TestData> testData = new List<TestData>();
if (string.IsNullOrEmpty(pageNumber))
{
testData = Data.Data.TestDataGet();
}
else
{
try
{
var pageInt = Convert.ToInt32(pageNumber);
List<ParameterSQL> parameter = new List<ParameterSQL>();
parameter.Add(new ParameterSQL { Name = "#pageOffset", Value = pageInt });
testData = Data.Data.TestDataGet(parameter);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
return Json(testData, JsonRequestBehavior.AllowGet);
}
The error that I'm experiencing is when I push the button the WebGrid disappears entirely. The reason that I need to be able to update the WebGrid data source is because my table is millions of lines long and I'm only grabbing them a few thousand at a time. Once the user reaches the end of the of the list I want them to be able to load more using a SQL query that I already have working. Any help would be great, thanks.

Cannot append to JS object in HighCharts callback, in Vue

I am using Vue 3.9.3, along with highcharts-vue 1.3.5 . I am trying to put into an object each highchart, as it loads, so then I have access to any chart I want like
myCharts.aChart or
myCharts.anotherChart,
so I can easily do myCharts.anotherChart.addData
In practice I do,
<highcharts :constructor-type="'stockChart'" :options="options" :callback="chartcallback" ></highcharts>
and then
data(){
return{
charts:{}
}
},
methods:{
chartcallback(hc){
let obj = {[hc.options.id] : hc};
this.charts = Object.assign(this.charts, obj);
//also tried this
const newChart = {id:hc.options.id, chart : hc};
this.$set(this.charts, newChart.id, newChart);
//also tried this
this.charts = Object.assign({}, this.charts, {
[hc.options.id] : hc
});
//also tried this
this.charts[hc.options.id]= hc;
console.log('test ', this.charts);
}
}
and then I would watch my data and each time they change, I would add data to each highchart,
watch: {
myData: {
immediate: true,
deep: true,
handler(){
this.charts.NameChart.series[0].setData(this.myData[0], true);
this.charts.DrinkChart.series[0].setData(this.myData[1], true);
//etc....
this.charts.NameChart or this.charts.DrinkChart should be constructed in chartcallback and NameChart, DrinkChart is the value of hc.options.id hc.options.id always has a value and it is there, I checked.
The problem is
at the end of chartcallback where I do console.log('test ', this.charts);, the produced obj is
//first time
{NameChart:chart}
//second time
{NameChart:chart}
but it should be
//first time
{NameChart:chart}
//second time
{NameChart:chart,
DrinkChart:chart}
It looks like it overwrites the this.charts every time chartcallback is called. I tried several methods, as I note, but nothing works.
What can I do ?
Thanks

How do I insert a value in a custom field in a table in Prestashop?

I added a custom field named "deldate" in "ps_orders" table, and I added a text box on "OPC" checkout page. Now when I click on order confirm button the value in the textbox should be saved in "deldate" field of "ps_orders" table.
The textbox is showing perfectly but in which files do I need to make changes to save the textbox value in the table?
(Theme is default one.)
class/order/order.php
class OrderCore extends ObjectModel
{
public $deldate;
}
And
public static $definition = array(
'fields' => array(
'deldate'=> array('type' => self::TYPE_STRING),
),
)
Shopping-cart.tpl
<div class="box">
<div class="required form-group">
<form method="post">
<label for="Fecha de entrega deseada">{l s='Desired delivery date' mod='deldate'}</label>
<input type="text" id="deldate" name="deldate" class="form-control" value="hello" />
</form>
</div>
</div>
Ok, I figured out the solution...
If you want to add some information to the order in the checkout process you have to save this informations elsewhere, if you look the cart table are very similar to order table.
Why you have to do this? Because you don't have an order before the confirmation by customer, so until the checkout is not complete that informations can't be saved in the order table.
So, first, create the field in database, in this case you have to add in ps_orders and in the ps_cart as well.
(In your case I suggest to use a DATETIME field)
Second, override the Order class:
class Order extends OrderCore
{
public function __construct($id = null, $id_lang = null)
{
self::$definition['fields']['deldate'] = array('type' => self::TYPE_DATE);
parent::__construct($id, $id_lang);
}
}
and the Cart class:
class Cart extends CartCore
{
public function __construct($id = null, $id_lang = null)
{
self::$definition['fields']['deldate'] = array('type' => self::TYPE_DATE);
parent::__construct($id, $id_lang);
}
}
Now we have to save the field during the checkout process, so we override the OrderController:
class OrderController extends OrderControllerCore
{
public function processAddress()
{
parent::processAddress();
// Here we begin our story
if(Tools::getIsset('deldate')) // Check if the field isn't empty
{
$deldate = Tools::getValue('deldate');
// Here you must parse and check data validity (I leave to you the code)
/* ... */
// Assign the data to context cart
$this->context->cart->deldate = $deldate;
// Save information
$this->context->cart->update();
}
}
}
Now you have to 'transport' this informations from the cart to the order, this will be done through the PaymentModule class, specifically with the validateOrder method.
So, another override:
class PaymentModule extends PaymentModuleCore
{
public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null)
{
$result = parent::validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method, $message, $extra_vars, $currency_special, $dont_touch_amount, $secure_key, $shop);
if($result)
{
$oldcart = new Cart($id_cart);
$neworder = new Order($this->currentOrder);
$neworder->deldate = $oldcart->deldate;
$neworder->update();
return true; // important
}
else
{
return $result;
}
}
}
After all of this you have the deldate field saved. However, I absolutely don't suggest this method, it's more safe and simple with a module and hooks... But this is another story :)
This will works only with the five steps checkout.
For next code lines, God save me...
If you want to works with OPC you have to dirty your hands with JS and override the OrderOpcController.
Start with the JS, edit the order-opc.js in js folder of enabled theme, find bindInputs function and append this lines of code:
function bindInputs()
{
/* ... */
$('#deldate').on('change', function(e){
updateDelDateInput(); // custom function to update deldate
});
}
then append to the file your custom function:
function updateDelDateInput()
{
$.ajax({
type: 'POST',
headers: { "cache-control": "no-cache" },
url: orderOpcUrl + '?rand=' + new Date().getTime(),
async: false,
cache: false,
dataType : "json",
data: 'ajax=true&method=updateDelDate&deldate=' + encodeURIComponent($('#deldate').val()) + '&token=' + static_token ,
success: function(jsonData)
{
if (jsonData.hasError)
{
var errors = '';
for(var error in jsonData.errors)
//IE6 bug fix
if(error !== 'indexOf')
errors += $('<div />').html(jsonData.errors[error]).text() + "\n";
alert(errors);
}
// Here you can add code to display the correct updating of field
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
if (textStatus !== 'abort')
alert("TECHNICAL ERROR: unable to save message \n\nDetails:\nError thrown: " + XMLHttpRequest + "\n" + 'Text status: ' + textStatus);
}
});
}
Then override the OrderOpcController, copy all the init method and change the line of code as below:
class OrderOpcController extends OrderOpcControllerCore
{
public function init()
{
// parent::init(); // comment or delete this line
FrontController::init(); // Very important!
// Then in this switch `switch (Tools::getValue('method'))` add your case
/* ... */
case 'updateDelDate':
if(Tools::isSubmit('deldate'))
{
$deldate = urldecode(Tools::getValue('deldate'));
// Here you must parse and check data validity (I leave to you the code)
/* ... */
// Assign the data to context cart
$this->context->cart->deldate = $deldate;
// Save information
$this->context->cart->update();
$this->ajaxDie(true);
}
break;
/* ... */
}
}
Obviously, is necessary the override of Order, Cart and PaymentModule as well.
PS: I hope that I didn't forget anything.
You can try also with this module
https://www.prestashop.com/forums/topic/589259-m%C3%B3dulo-selector-fecha-en-pedido/?p=2489523
Try this in the override of the class Order
class Order extends OrderCore
{
public function __construct($id = null, $id_lang = null)
{
parent::__construct($id, $id_lang);
self::$definition['fields']['deldate'] = array('type' => self::TYPE_STRING);
Cache::clean('objectmodel_def_Order');
}
}
The Cache::clean is need because getDefinition tries to retrieve from cache, and cache is set without the override on parent::__construct
I then tried to create a new empty Order and get the definition fields and it showed there, so it should save to mysql
$order = new Order();
var_dump(ObjectModel::getDefinition($order));exit;

sapui5 data from json

Have problem to read data from json. My login.json file
{
"Users": [
{
"login" : "admin",
"password" : "admin"
}
]
}
Here is my login.xml.view
<core:View
controllerName="sap.ui.demo.myFiori.view.login"
xmlns="sap.m"
xmlns:l="sap.ui.layout"
xmlns:core="sap.ui.core" >
<Page
title="{i18n>LoginIn}">
<VBox
class="marginBoxContent" >
<items>
<Label text="User" />
<Input
id="nameInput"
type="Text"
placeholder="..." />
<Label text="password" />
<Input
id="passwInput"
type="Password"
placeholder=" ..." />
<Text id="description" class="marginOnlyTop" />
<Button text="Login" press="handleContinue" />
</items>
</VBox>
</Page>
</core:View>
and login.controller.js
jQuery.sap.require("sap.ui.demo.myFiori.util.Formatter");
sap.ui.controller("sap.ui.demo.myFiori.view.login", {
handleContinue : function (evt) {
var name = this.getView().byId("nameInput").getValue();
var paswd = this.getView().byId("passwInput").getValue();
if (name == "log" && paswd == "pass") {
var context = evt.getSource().getBindingContext();
this.nav.to("Master", context);
}
else {
jQuery.sap.require("sap.m.MessageToast");
sap.m.MessageToast.show("Wrong login");
}
}
});
This login screen works, but I can't get login and password from json file and currently these data are taken from if sentence, which is not good. Any suggestions?
First, I am assuming that this is just a test app, as having the correct plain text auth credentials actually in the client app is rather bad practice ...
The crux of your question seems to be: "How can I access JSON data from a file?"
There is a Q&A already on SO with that theme: How to get data from a json file? but if you want to use a model, which is a common practice in UI5 apps, then you could:
1) Create a JSON model, specifying the name of the JSON file; the JSONModel mechanism will take care of the loading; assign this to the view
this.getView().setModel(new sap.ui.model.json.JSONModel('login.json'), "login");
2) Access the data in the JSON model when you need to check, using the getData() method
// Note - extremely bad practice - don't do this for real!
var authinfo = this.getView().getModel("login").getData().Users[0];
if (name == authinfo.login && paswd == authinfo.password) {
....
(I'm indexing 0 of Users as you seem to have your authinfo inside an array)
Maybe I defined something wrong before but now it works. I changed login.controller.js. Now it looks like this:
jQuery.sap.require("sap.ui.demo.myFiori.util.Formatter");
sap.ui.controller("sap.ui.demo.myFiori.view.login", {
onInit: function () {
var oModels = new sap.ui.model.json.JSONModel("login.json");
sap.ui.getCore().setModel(oModels);
},
handleContinue : function (evt) {
var authinfo = this.getView().getModel().getData().Users[0];
var name = this.getView().byId("nameInput").getValue();
var paswd = this.getView().byId("passwInput").getValue();
if (name == authinfo.login && paswd == authinfo.passw) {
var context = evt.getSource().getBindingContext();
this.nav.to("Master", context);
}
else {
jQuery.sap.require("sap.m.MessageToast");
sap.m.MessageToast.show("Wrong login");
}
}
});

How to send JSON using JSF2 Primefaces Request Context to Highchart?

Hi I've been strugling with this for hours, I want to send my POJO in JSON format using Primefaces Request Context to a Highchart inside my JSF to update its value.
Basically I am following this solution of #Bhesh Gurung from his own stackoverflow question
but I cant seem to make it work. Right now it is throwing a:
Cannot find component with identifier "pieData" referenced from "j_idt31".
I want to sucessfully create a highchart using the JSON data through the Primefaces Request Context. Please help Thanks in advance.
This are my codes below
#ManagedBean
#ViewScoped
public class PieDataProvider {
public void retrievePieData() {
List<String> categories = new ArrayList<String>();
categories.add("Electronic");
categories.add("Food");
categories.add("Liguor");
categories.add("Stationary");
categories.add("Mechanical");
List<Integer> itemCounts = new ArrayList<Integer>();
itemCounts.add(5);
itemCounts.add(20);
itemCounts.add(1);
itemCounts.add(50);
itemCounts.add(10);
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.addCallbackParam("categories", new Gson().toJson(categories));
reqCtx.addCallbackParam("itemCounts", new Gson().toJson(itemCounts));
System.out.println(categories);
}
}
My xhtml page5.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition template="/template/common/commonLayout.xhtml">
<ui:define name="content">
<h:head>
<script type="text/javascript">
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"
src="http://code.highcharts.com/highcharts.js"
src="http://code.highcharts.com/modules/exporting.js"
</script>
<script type="text/javascript">
function feedPieData(xhr, status, args) {
var categories = eval('(' + args.categories + ')');
var itemCounts = eval('(' + args.itemCounts + ')');
options.xAxis.categories = categories;
var series = {
data : []
};
series.name = new Date().toString();
series.data = itemCounts;
options.series = [ series ];
chart = new Highcharts.Chart(options);
}
</script>
</h:head>
<h:body>
<p:commandLink action="#{pieDataProvider.retrievePieData}"
oncomplete="feedPieData(xhr, status, args);" value="Pie chart demo"
update="pieData" />
</h:body>
</ui:define>
<ui:define name="footer">
<h2>This is page5 Footer</h2>
</ui:define>
</ui:composition>
UPDATE: MODIFIED XHTML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:body>
<ui:composition template="/template/common/commonLayout.xhtml">
<ui:define name="content">
<h:head>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$('#container')
.highcharts(
{
chart : {
plotBackgroundColor : null,
plotBorderWidth : null,
plotShadow : false
},
title : {
text : 'Most used words, 2010'
},
tooltip : {
pointFormat : '{series.name}: {point.percentage}',
percentageDecimals : 1
},
plotOptions : {
pie : {
allowPointSelect : true,
cursor : 'pointer',
dataLabels : {
enabled : true,
color : '#000000',
connectorColor : '#000000',
formatter : function() {
return '<b>'
+ this.point.name
+ '</b>: '
+ this.percentage
//+ ' %'
;
}
}
}
},
series : [ {
type : 'pie',
name : 'Browser share',
data : [ [ 'Red', 45.0 ],
[ 'Orange', 26.8 ], {
name : 'Yellow',
y : 12.8,
sliced : true,
selected : true
}, [ 'Green', 8.5 ],
[ 'Blue', 6.2 ],
[ 'Violet', 0.7 ] ]
} ]
});
});
</script>
<script type="text/javascript">
function feedPieData(xhr, status, args) {
var categories = JSON.parse(args.categories);
var itemCounts = JSON.parse(args.itemCounts);
var series = {
data : []
};
options.series[0].data.length = 0;
series.data = categories;
series.data = itemCounts;
options.series = [ series ];
chart = new Highcharts.Chart(options);
}
</script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
</h:head>
<h:body>
<div id="container"
style="min-width: 400px; height: 400px; margin: 0 auto"></div>
<h:form>
<p:commandLink action="#{pieDataProvider.retrievePieData}"
oncomplete="feedPieData(xhr, status, args);"
value="Pie chart demo" />
</h:form>
</h:body>
</ui:define>
<ui:define name="footer">
<h2>This is page5 Footer</h2>
</ui:define>
</ui:composition>
</h:body>
</html>
You seem to fail to understand that Highcharts is a JavasScript environment that runs solely on the client, while PrimeFaces/JSF is on the server side and they act in this context simply as HTML, CSS and JavaScript code generator.
In your particular case, PrimeFaces is simply used to send data from the server to the client via RequestContext. After AJAX call completes and effectively, serialized data is received by the client, you call a JavaScript function that creates a Highcharts JS component entirely on the client from the received data.
All in all, it yields us with the following setup.
** The view elements **
<h:form>
<p:commandLink action="#{pieDataProvider.retrievePieData}"
oncomplete="feedPieData(xhr, status, args);"
value="Generate pie chart" />
</h:form>
** The JavaScript **
<script type="text/javascript">
function feedPieData(xhr, status, args) {
var categories = JSON.parse(args.categories);//serialized data from server
var itemCounts = JSON.parse(args.itemCounts);//serialized data from server
//next you create the chart and show it
}
</script>
** The action method **
public void retrievePieData() {
List<String> categories = generateCategories();
List<Integer> itemCounts = generateItems();
RequestContext reqCtx = RequestContext.getCurrentInstance();
reqCtx.addCallbackParam("categories", new Gson().toJson(categories));//additional serialized data to be sent
reqCtx.addCallbackParam("itemCounts", new Gson().toJson(itemCounts));//additional serialized data to be sent
}