I'm a noobie of PHP and AngularJS.
I have a webpage that communicates to a web serves with PHP - AJAX. It queries a database, and echoes the result (a big table) in an html placeholder.
I want to print the content of that table in a downloadable PDF file when the user pushes a button.
I want to use PDFmake and now it works well for test purpose, but how can I pass that content of my table to AngularJS' app?
Maybe should I pass table's id to docDefinition content? In that case I don't know how to do that.
Note: Maybe my approach is uncorrent cause I have to relegate PHP to different tasks and use AngularJS to query the Database, but for now I want to mantain this approach.
Thank You
I suggest you use an angular service (as explained in the docs
)
var bigTableApp = angular.module('bigTable',[])
bigTableApp.factory('BigTableSrv', ['$resource',
function($resource) {
return $resource('URL_to_php_backend', {}, {
query: {
method: 'GET',
params: {param1: 'value 1', param2: 'value 2'},
isArray: true
}
});
}
]);
Then, you can use it in a controller to fetch data from the back-end and build a table structure in PDFmake's table format:
bigTableApp.controller('BigTableController', ['$scope', 'BigTableSrv',
function BigTableController($scope, BigTableSrv) {
$scope.bigTable = BigTableSrv.query();
$scope.pdfMakeTable = {
// array of column widths, expand as needed
widths: [10, *, 130],
body: []
};
$scope.printTable = function() {
pdfMakeTable.body = $scope.bigTable.map(el => {
// process each element of your "big table" to one line of the
// pdfMake table, size of return array must match that of the widths array
return [el.prop1, el.prop2, el.prop3]
});
// create the pdfMake document
let docDefinition = {
content: [ pdfMakeTable ]
}
// print your pdf
pdfMake.creatPdf(docDefinition).print()
}
}
]);
Related
I got a project require angularjs datatable (i-lin) to populate large amount of data. Therefore, i decided to use server side processing and Ajax call to get my PHP data populate into the angularjs datatable. Currently, i could show the static columns and data perfectly however.......
Problem
The Ajax(api call) needs sometime to request the data therefore now my page will show the static data columns first. A few seconds later, page will refresh again then append the new columns.
Which means, user will see the static datatable columns first, After 1 second will see another datatable. It looks very weird for user.
Target
Instead of show the static columns, I would like ensure all data has been returned from Ajax then only show the complete table.
Code
html
<table id="saleReport"
class="report-table table-striped table table-bordered
table-condensed table-hover data-table"
datatable="" dt-options="dtOptions" dt-columns="dtColumns"
dt-instance="dtInstance">
Angularjs
The Module.fetchSalesData are API call from the PHP
$scope.dtOptions = DTOptionsBuilder
.newOptions()
.withOption('ajax', function (data, callback, settings) {
// set dataSrc
settings.sAjaxDataProp = 'trans';
Module.fetchSalesData({
draw: data.draw,
length: data.length,
start: data.start,
search : data.search.value,
count_again : $scope.countAgain,
startdate: $filter('date')($scope.item.startdate, 'yyyy-MM-dd'),
enddate : $filter('date')($scope.item.enddate, 'yyyy-MM-dd'),
payee_id: $scope.item.payee_id,
staff_id: $scope.item.staff_id,
order: data.order
}).then(function(res) {
$scope.payment_methods = res.data;
callback(res);
$scope.countAgain = false;
})
})
.withOption('serverSide', true)
//This is static dtColumns, User will see this first
$scope.dtColumns = [
DTColumnBuilder.newColumn('invoice_date')
.withTitle('Date')
.withOption('sWidth', '10%'),
DTColumnBuilder.newColumn('ref_num').withTitle('Description')
];
//Set timout waiting server returned **$scope.payment_methods**
//in order to generate dtcolumns dynamically
setTimeout(function() {
angular.forEach($scope.payment_methods, function (value) {
$scope.dtColumns.push(
DTColumnBuilder.newColumn(value).withTitle(value)
.notSortable().withClass('text-right')
.withOption('stateSave', true)
.renderWith(function (data, type, full) {
data = typeof data === 'undefined' ? '0.00' : data;
return $filter('currency')(data, '');
}),
)
});
}, 1000);
Tried
What i have try is using destroy the first table and keep the latest table but it failed
var table = $('#saleReport').DataTable();
table.clear().destroy();
Appreciated of you guys could give me the ideas.
I'm working on a Extjs 4 application and I'm at a point where I need to create view components dynamically.
I have a store that's loaded with new items when I select a value from a combobox. And I want to create a new view component for each item the new store has.
I'm using Extjs 4 with the MVC architecture.
This is the function that creates a new combobox that's fired when I choose an Item from another combo :
function createComboBox(label) {
var combo = new Ext.form.ComboBox({
displayField: 'combo',
typeAhead: true,
mode: 'local',
forceSelection: true,
triggerAction: 'all',
emptyText: 'Select item...',
selectOnFocus: true,
fieldLabel: label
});
return combo;
}
This is the code inside my "select combobox" handler event :
onSelectedValue: function (combo) {
var selected = combo.getValue();
var guiDataStore = this.getGuiDataStore();
guiDataStore.getProxy().url = 'gui_comp_items.php?id_metric=' + selected;
guiDataStore.load({
params: {
id_metric: selected
},
scope: this,
callback: function () {
var paramsRef = this.getParams();//this is the view where I'd like to create the combobox
var total = guiDataStore.getTotalCount();
if (total > 0) {
guiDataStore.each(function (model) {
if (model.get('type_guicomp') == 'combobox') {
paramsRef.down('fieldset[id=filterfieldset]').add(createComboBox(model.get('name_filter')));
paramsRef.down('fieldset[id=filterfieldset]').doLayout();
}
})
}
}
})
}
So my problem is, the first time I choose an item from the existing combobox and total = 0 , no combobox is created and everything is fine, then when I choose a value that returns total = 2, 2 new comboboxes are created, that's perfect. BUT, when right after that, I choose again a value with total = 0, the store is not updated and I STILL get 2 new comboboxes.
Is there a problem with my callback? Please any help would be much appreciated.
Once guiDataStore has 2 records in it, why would it be empty next time?
As in, do you empty the store between the various callback calls?
I am programming in php,
I want to take an array I have (which is extracted from mysql result set), convert it to JSON and then use it in dojox.grid.DataGrid.
I got an idea from this link:
I used the following on the array (in a file called getJSON.php)
echo $ajax = "{identifier: 'db_id', 'items':".json_encode($array)."}";
Then I try doing this (in my main page):
var store = new dojo.data.ItemFileWriteStore({ url: 'getJSON.php' });
Everything else is exactly as the Dojo documentation specifies.
The grid shows up, but doesn't load the data and instead writes Sorry, an error occurred
Does anyone know the reason? Hopefully I gave you enough to go on.
i don't use ItemFileWriteStore for that ! They changed a lot since Dojo 1.6 , so maybe you looked at something not up to date.
Try this code:
// Load the neccessary components (This is dojo with AMD ) !
require(["dojo/aspect",'dojo/_base/lang', 'dojox/grid/DataGrid'
,'dojo/dom' , 'dojo/store/JsonRest','dojo/data/ObjectStore',
'dojo/domReady!'],
function(aspect,lang, DataGrid, dom,JsonRest,ObjectStore){ // Map components to vars...
var store = new JsonRest({
target: "getJSON.php" // Use a URL that you can open up in a browser.
});
/*layout for the grid, you will have to adapt this to your columns !!!*/
var layout = [[
{'name': 'Filename', 'field': 'documentName', 'width': '300px'},
{'name': 'Size', 'field': 'fileSize', 'width': '100px'},
{'name': 'Id', 'field': 'id', 'width': '200px'}
]];
dataStore=ObjectStore({objectStore: store}); // Transform to Objectstore !
/*Now we create a new grid*/
var grid = new DataGrid({
id: 'grid',
store:dataStore, // Connect the store
autoWidth:false,
structure: layout, // Connect the layout
rowSelector: '0px'});
grid.placeAt("yourTargetDivId"); // Has to be an existing DOM Element with id !
grid.startup(); // START IT !
});
Please try this code by echoing something simple like this first:
echo '[{"id":"1","fileSize":"100kb","documentName":"Lucian !"},
{"id":"2","fileSize":"900kb","documentName":"Pew Pew !"}]';
And after that with your own JSON...
i am working in extjs4 MVC where I have been working on task to create question answer page functionality.There are 4 questions to be displayed with there options.I have getting all the selected questions and answers in controller.But I didnot know how to send to srver side using models method.I am getting stuck at this point.
Here is my some controller code
1)
check:function()
{
console.log("Inside check function.");
//creating objects in javascript
var obj=new Object();
for(var i=0;i<=5;i++)
{
var inputs = document.getElementsByName(i);
var radio = "";
for (var j = 0; j < inputs.length; j++) {
if (inputs[j].checked) {
name = inputs[j].name;
value = inputs[j].value;
//obj[i].name1=name;
obj[i]={'questionId':name,'option':value};
console.log("questionId="+name +" value="+ value);
console.log("object name="+ obj[i].questionId+" Object value="+obj[i].option);
}// End of if statment
}// End of inner for loop
}//End of outer for loop
}// End of check function
2)here is I have getting some output in firebug
questionId=1 value=Aus QbqnsController.js:39
questionId=2 value=india QbqnsController.js:39
questionId=3 value=England QbqnsController.js:39
questionId=4 value=Srilanka
Actually i want to use model class methods save() . but how can I use it.
please give me some suggestions.
3)here is my model classs
Ext.define('Balaee.model.qb.QbqnsModel',{
extend: 'Ext.data.Model',
idproperty:'questionId',//fields property first position pk.
fields: ['questionId','question','languageId','userId','creationTime','questionStatusId','keyword'],
hasMany:{
model:'Balaee.model.qb.QbqnsoptionModel',
foreignKey:'questionId',
name:'options',
},
proxy:
{
type:'ajax',
api:
{
read:'http://localhost/balaee/balaee/index.php?r=QuestionBank/qbpaper/setuseranswer',
create:'http://localhost/balaee/balaee/index.php?r=QuestionBank/qbpaper/setuseranswer',
},//end of api
reader:
{
type:'json',
},//end of reader
writer:
{
type:'json',
root:'records',
},//End of writer
}
});
If you're using Ext MVC and you're questions are model instances stored inside a store, you can use store.sync() which will batch the data in different states (add, edit, deletes etc) and sync them with the relevant store or model proxy url, or the api urls specified.
This has the benefit of sending arrays of objects back in a single request, but then of course you need to separate them on the server side before processing.
Inside your function you can send them using Ext.Ajax.request
Ext.Ajax.request({
url: 'your_server_page.php ',
params: {
Your_Object_Name : JSON.stringify(Your_Object_Array)
}
});
Here is what I have so far:
var Item = Backbone.Model.extend({
defaults: {
id: 0,
pid: 0,
t: null,
c: null
},
idAttribute: 'RootNode_', // what should this be ???
url: 'page.php'
});
var ItemList = Backbone.Collection.extend({
model: Item,
url: 'page.php',
parse: function(data) {
alert(JSON.stringify(data)); // returns a list of json objects, but does nothing with them ???
}
});
var ItemView = Backbone.View.extend({
initialize: function() {
this.list = new ItemList();
this.list.bind('all', this.render, this);
this.list.fetch();
},
render: function() {
// access this.list ???
}
});
var view = new ItemView();
Current (expected) json response:
{
"RootElem_0":{"Id":1,"Pid":1,"T":"Test","C":"Blue"},
"RootElem_1":{"Id":2,"Pid":1,"T":"Test","C":"Red"},
"RootElem_2":{"Id":3,"Pid":1,"T":"Test2","C":"Money"}
}
This successfully polls page.php and the backend acts on $_SERVER['REQUEST_METHOD'] and returns the required information, however I don't know why the collection is not filled.
In the parse function of ItemList it properly shows me all the output, but it does nothing with it.
I left some comments in the code for some more precise questions, but the main question is why doesn't the collection populate with the obviously received data?
Modify your parse method to:
parse: function(response){
var parsed = [];
for(var key in response){
parsed.push(response[key]);
}
return parsed;
}
To follow conventions, change list inside ItemView to model. Also in render():
render: function() {
var template = _.template("<div>some template</div>");
this.model.each(function(item){
this.$el.append(template(item.toJSON()));
}, this);
return this;
}
The parse method you're supposed to be returning the data after doing whatever necessary parsing is required for it.
The common use case for parse would be if you're sending back an object of a form like:
{ "id" : "NaN", "tasks": [ *all your models in a list here *] }
then you'd use parse like so:
parse: function (data) {
return data.tasks
}
Backbone then handles the rest.
Is there a particular reason why you're sending the data back in that dictionary format? It's not exactly clear how you intend to map that to each model of the collection. Is the key irrelevant? if so, you should be passing back a list of the objects in the values.(Although see note at bottom). If not, and you want to attach it to the models, it should be moved to the object you're using as a value and send back a list.
* Note: Don't actually send back a JSON list bare. There is an exploit for GET requests that relies on lists being valid javascript on their own, where a malicious site can use the Array object and override it to use a script tag to your API to use the users credentials to pull down whatever information is available in that call. Instead, when wanting to send back a list you should use something like this:
{ result: [*list here*] }
Then you just use the parse method above to extract the list.