Jsreport shows different result when rendering from client and server - javascript

I have a template named A and a test Json stored in server.
Using normal setup for jsreport to render PDF work wonder in the server.
Now I want to use Jsreport_client.js to render. I do an AJAX call getJSON to other server and use jsclient to render. But now the data is not sent/processed correctly. The key located near the root of JSON object is correct but the rest is not. Note that the very same JSON render on server correctly
EDIT:
Below is the call
$.getJSON(AJAXurl).success(function (people) {
jsreport.serverUrl = 'http://localhost:5488';
var request = {
template: {
shortid:"rJPUhdmv"
},
data: people
};
jsreport.render('_blank', request);
})
Below is the returned request structure
{
"responseHeader":{
"status":0,
"params":{
"fq":"{!frange l=0.80 }query($q)",
"q":"{!percentage}etco~",
"group.field":"ent_id"
}},
"grouped":{
"ent_id":{
"ngroups":3,
"groups":[{
"groupValue":"214493",
"doclist":{"numFound":1,"docs":[
{
"add_city":"London",
"add_street":"Devonshire Street",
"nam_comp_name":"ETCO INTERNATIONAL COMMODITIES LTD.",
"add_country":"GB",
"add_id":"668638",
"score":1.0}]
}},OTHER GROUP.....]}}},
"highlighting":{
"C":{
"nam_comp_name":["<span class=\"highlight\">ETO</span>"]}
}}
And below is the handler in server
// Can not read any parameters
</thead>
{{#each grouped.ent_id.groups}}
</tr>
<td>{{offsetIndex #index}}</td>
{{#each doclist.docs}}
<td>{{this.nam_comp_name}}</td>
<td>{{convertScore this.score}}</td>
<td>{{this.add_country}} {{this.add_city}} {{this.add_street}}</td>
<td>{{lis_name}}</td>
{{/each}}
</tr>
{{/each}}
Another handler which has both correct and incorrect/unreadable data
{{#responseHeader.params}}
<tr>
<th>Search term</th>
<td>{{sanitizeQuery this.q}}</td> // Read correctly
</tr>
<tr>
<th>Sanction List: </th>
<td>{{sanitizeQuery this.fq.[0]}}</td> // Incorrectly
</tr>
<tr>
<th>Countries:</th>
<td>{{sanitizeQuery this.fq.[1]}}</td> // Incorrectly
</tr>
{{/responseHeader.params}}
<tr>
<th>Search by:</th>
<td>"Method of searching"</td> // Incorrectly
</tr>
<tr>
<th>Found total:</th>
<td>{{grouped.ent_id.ngroups}}</td> // Read correctly
Helpers
function offsetIndex(index) {
return index+1;
}
function convertScore(score) {
a = parseFloat(score);
return a*100;
}
function sanitizeQuery(query) {
a =query
.replace(/{+.*?}+/g, "")
.replace(/\[\[|\]\]/g, "")
.replace(/<.*?>/g, "")
.replace(/add_country:/,"")
.replace(/program_number:/,"")
.replace(/~/,"");
return a;
}

This was a bug with array serialization in jsreport browser client. Now it is fixed.
Please update to jsreport-browser-client-dist#1.0.2 or update whole jsreport where you can also find it in jsreport#1.0.9

Related

AngularJS: weird behavior with the 2-way binding (ng-repeat)

I'm using AngularJS in a Firebase app and I have a function where I do some inner join to get some data. More details here. After getting the response from the firebase api I create an object and push it into an array (a scope variable). I see in the debug that the data has been retrieved and that the $scope variable is filled correctly. The problem is that it is not showing in the ng-repeat.
My function:
$scope.getMessagesByRegion = function(regionId){
console.log('Function start');
var rootRef = firebase.database().ref();
var regionMessagesRef = rootRef.child("region_messages/"+ regionId);
$scope.messages_by_region = []; // Here I reset the scope variable
regionMessagesRef.on('child_added', function(rmSnap) {
var messageRef = rootRef.child("messages/"+rmSnap.key);
messageRef.once('value').then(function(msgSnap){
var msg = {
key : msgSnap.key,
name : msgSnap.val().name,
type : $scope.getTypeName(msgSnap.val().type),
show_only_once : rmSnap.val().show_only_once,
pre_requisite_message : rmSnap.val().pre_requisite_message
}
console.log(msg); // here I see the object in the console. it is OK
$scope.messages_by_region.push(msg); // pushing the item
console.log('----------------');
console.log($scope.messages_by_region);
})
});
}
My HTML:
<table class="table">
<thead>
<tr>
<th>Message name</th>
<th>Type</th>
<th>Show only once</th>
<th>Pre requisite</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="msg in messages_by_region">
<td ng-bind="msg.name"></td>
<td ng-bind="msg.type"></td>
<td ng-bind="msg.show_only_once"></td>
<td ng-bind="msg.pre_requisite_message"></td>
</tr>
</tbody>
</table>
This is what I see in the console:
The problem is that even having an object in the array it is not shown in the view. It is like there was an empty array set to the $scope.messages_by_region variable
I'm having a hard time figuring out what I'm doing wrong. Can you see what's wrong with my function?
Thanks for any help.
try,
$scope.$apply(function(){
$scope.messages_by_region.push(msg);
});
or,
$scope.messages_by_region.push(msg);
$scope.$apply();
Since you're using async functions (Cosuming of firebase API) you should tell angular to refresh the HTML;
Use
$scope.$diggest()
More information you can find on https://www.sitepoint.com/understanding-angulars-apply-digest/
As you are performing Async calls you need to tell angular to refresh the changes in the value with $apply call you can do it with:
$scope.getMessagesByRegion = function(regionId) {
console.log('Function start');
var rootRef = firebase.database().ref();
var regionMessagesRef = rootRef.child("region_messages/" + regionId);
$scope.messages_by_region = []; // Here I reset the scope variable
regionMessagesRef.on('child_added', function(rmSnap) {
var messageRef = rootRef.child("messages/" + rmSnap.key);
messageRef.once('value').then(function(msgSnap) {
var msg = {
key: msgSnap.key,
name: msgSnap.val().name,
type: $scope.getTypeName(msgSnap.val().type),
show_only_once: rmSnap.val().show_only_once,
pre_requisite_message: rmSnap.val().pre_requisite_message
}
$scope.$apply(function() {
console.log(msg); // here I see the object in the console. it is OK
$scope.messages_by_region.push(msg); // pushing the item
console.log('----------------');
console.log($scope.messages_by_region);
});
});
});
}
For more information on this behavior you can also read article describing the problem here

Angular Datatables REST based per page data with explicit table rendering

I have followed the approach "DataTables: Custom Response Handling" by Fabrício Matté. However, my requirement is to avoid rendering of table's rows and columns via callback. Instead, would like to traverse the current ajax request returned json data and render explicit html (tr/td) to have more control. Due to this, currently i see data shown twice on my table. At the same time, i understand that callback is rendering the page related buttons: prev, 1,2 next etc and click events which i would like to reuse and wan't to avoid custom implementation.
JS:
function notificationsCtrl($scope,$http,$resource, DTOptionsBuilder, DTColumnBuilder) {
var vm = this;
vm.notifications = [];
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withOption('serverSide', true)
.withOption('ajax', function(data, callback, settings) {
// make an ajax request using data.start and data.length
$http.get('notifications/list?page=' + (((data.start)/10)+1)).success(function(res) {
// map your server's response to the DataTables format and pass it to
// DataTables' callback
callback({
recordsTotal: 120,
recordsFiltered: 120,
data: res
});
vm.notifications = res;
});
})
.withDataProp('data') // IMPORTANT¹
.withOption('processing', true)
.withPaginationType('full_numbers');
$scope.dtColumns = [
DTColumnBuilder.newColumn('notificationId').withTitle('notificationId'),
DTColumnBuilder.newColumn('createUserId').withTitle('createUserId'),
DTColumnBuilder.newColumn('Language').withTitle('language')
];
}
HTML: sample but actual will require extra processing for some of the td tags
<table datatable="" dt-options="dtOptions" dt-columns="dtColumns" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Language</th>
<th>Last Updated</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="notification in wynkCMSToolApp.notifications">
<td>{{ notification.notificationId }}</td>
<td>{{ notification.title }}</td>
<td>{{ notification.Language }}</td>
</tr>
</tbody>
</table>
If you want to render directly in the HTML, consider using the Angular renderer. However, such renderer does not support the server side processing.
So I recommend you use the server side processing along with the columns.render function.
Here an example of using the render function.

Angularjs Smart table not working for Dynamic data

I have a situation where i am using angularJs smart table for filtering.
html:
<section class="main" ng-init="listAllWorkOrderData()">
<table st-table="listWorkOrderResponse">
<thead>
<tr>
<th st-sort="id">ID <i></i></th>
<th st-sort="project">Project <i></i></th>
</tr>
</thead>
<tbody ng-repeat="workOrder in listWorkOrderResponse">
<tr>
<td>{{workOrder.id}}</td>
<td>{{workOrder.project}}</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</section>
I am testing for 2 different cases.
In my controller first i call the same function but send dummy array and in the second case i send the array received from the api call.
1. Dummy data
$scope.listAllWorkOrderData = function () {
var listWorkOrderResponse = [{"id":"1","project":"project1"},{"id":2,"project":"project2"},{"id":"3","project":"project3"}];
}
2. I am using a service and fetching data through api.
$scope.listAllWorkOrderData = function () {
TestService.listAllWorkOrderData().then(function (response, status, headers, config) {
if (response != undefined && response != null) {
if (!$scope.listWorkOrderResponse) {
$scope.listWorkOrderResponse = [];
}
$scope.listWorkOrderResponse = response;
}, function (response, status, headers, config) {
console.log(response);
});
When i am using case1 the sorting works fine.
But when i use case2 the sorting does not work. Onclick of it the data just disappears.
I tried debugging to see whether the listAllWorkOrderData function is being called again when we click on the filter.But it is just called once when the page is loaded to populate the table.So that means the data is present in the listWorkOrderResponse. Then why is it not sorting?
I checked the response for both the situation by printing them the only difference i found was that the listWorkOrderResponse which comes from the api call has a $$hashKey: "object:363" added to it.
Can anyone point me what mistake i am doing.
I was able to resolve this issue by using stSafeSrc attribute
In the controller we add
$scope.listAllWorkOrderData = function () {
TestService.listAllWorkOrderData().then(function (response, status, headers, config) {
if (response != undefined && response != null) {
if (!$scope.listWorkOrderResponse) {
$scope.listWorkOrderResponse = [];
}
$scope.listWorkOrderResponse = response;
// we add one more list.
$scope.displayedWOList = [].concat($scope.listWorkOrderResponse);
}, function (response, status, headers, config) {
console.log(response);
});
and then in the html table we add the stSafeSrc attribute.
stSafeSrc attribute from the Smart Table document
http://lorenzofox3.github.io/smart-table-website/
stSafeSrc attribute
If you are bringing in data asynchronously (from a
remote database, restful endpoint, ajax call, etc) you must use the
stSafeSrc attribute. You must use a seperate collection for both the
base and safe collections or you may end up with an infinite loop.
<section class="main" ng-init="listAllWorkOrderData()">
<table st-table="displayedWOList" st-safe-src="listWorkOrderResponse">
<thead>
<tr>
<th st-sort="id">ID <i></i></th>
<th st-sort="project">Project <i></i></th>
</tr>
</thead>
<tbody ng-repeat="workOrder in displayedWOList">
<tr>
<td>{{workOrder.id}}</td>
<td>{{workOrder.project}}</td>
</tr>
<tr>
<td></td>
</tr>
</tbody>
</table>
</section>
Why it is not working i don't know but yo can solve it by doing like below
repeat your response & create a new object & push it into an array..
var res = [];
for(var i=0; i<response.length; i++) {
var x = {"id":response[i].id, "project":response[i].project};
arr[i] = angular.copy(x);
}

Knockout.js: Updating objects loaded with mapping plugin

I want to render a table containing a list of objects my server is sending me. I'm currently doing this:
<table>
<thead>
<tr>
<th>id</th>
<th>Name</th>
<th>Status</th>
</tr>
</thead>
<tbody data-bind="foreach: services">
<tr>
<td data-bind="text: id"></td>
<td data-bind="text: name"></td>
<td data-bind="text: status"></td>
</tr>
</tbody>
</table>
And the Knockout.js binding part:
var mappedData = komapping.fromJSON('{{{ services }}}');
ko.applyBindings({services: mappedData});
services is a variable containing JSON data and the whole page is rendered with handlebars. So far so good. I'm able to render the data received in the table.
Now the problem: I'd like to receive a notification which tells me that the status of a service has changed, and update the corresponding object within mappedData. The problem is that mappedData seems pretty opaque and I'm unable to retrieve an object and update it given its id.
Help appreciated!
Your mappedData variable at this point will be a knockout array with a bunch of objects that contain knockout observables.
So all you have to do is change the status observable in the correct object from the array.
function updateServiceStatus(id, status) {
var service = mappedData().filter(function(e) { return e.id() == id; });
if (service.length) {
service[0].status(status);
}
}
To get the object, you can write a helper function that will retrieve for you a service object. You could do something like this (assuming mappedData is an observableArray and id observable) :
function get_service_by_id(service_id){
for(var i=0;i<mappedData().length;i++){
if (mappedData()[i].id() === service_id){
return mappedData()[i];
}
}
return false;
}

Reloading using Angular

Hello friends from SO!
I'm new into angular, and I'm trying to keep a table always updated with the information comming from a PHP webservice.
I'm demanding the information the first time using the following:
HTML
<div class="block" ng-controller="demandar_informacion" ng-init="visualizacion_masiva()">
<h1 class="block_header">Welcome admin</h1>
<p class="block_info"></p>
<table>
<thead>
<tr>
<th ng-repeat="header in headers ">{{header}}</th>
</tr>
</thead>
<tr ng-repeat="disponible in disponibles">
<td ng-repeat="(variable, valor) in disponible">{{valor}}</td>
</tr>
</table>
</div>
Then I'm using the following code to get the information:
Js Angular:
function demandar_informacion($scope, $http) {
//pedido de visualización masiva
$scope.visualizacion_masiva = function() {
var address = "http://127.0.0.1/usa/_code/index_records.php"
+ "?ac=view_all"
var pedido = $http({
method: 'GET',
url: address
})
.success(function(data, status) {
$scope.errors = data.error;
$scope.headers = data.headers;
$scope.disponibles = data.disponibles;
$scope.eliminados = data.eliminados;
$scope.info = data.info;
});
};
}
Main Q:
Is there any way I could re-send the HTTP packet and update the information every, let's say, 3 or 5 seconds? as It's rapidly changing.
Auxiliary:
At the same time, this fragment of code, seems to be altering the order of the values I have on the array, or it might be previously altered somewhere in the Angular code. I've checked the PHP and the Json string seems to be in right conditions, but when it comes to printing the values, it completely looses it's native order (shows the elements in an improper / unknown order)... anyone has a clue?
<tr ng-repeat="disponible in disponibles">
<td ng-repeat="(variable, valor) in disponible">{{valor}}</td>
</tr>
Thanks in advance!
Chris C. Russo
Update
$scope.update = function() {
$timeout(function() {
$http.get('lol').success(function() {
$scope.update();
});
}, 5000);
};
Old
Simplest way to do this:
$interval(function() {
demandar_informacion();
}, 5000);
buuuuutttt as MichaL pointed out in the comments what will happen is that 5 seconds will get eaten up as it becomes 5, 4, 3, 2, 1, DDOSing yourself due to the time it takes to complete the request.
Other ways:
Use firebase to wait and call the load function.
Long poll your php script.
You can use the $timeout service to call the server every few seconds. Or use websockets to push the changes from the server to your Angular app (with Ratchet, perhaps (http://socketo.me/))

Categories

Resources