I have featherjs app and trying to use datatables. I am using ajax datasource with configuration below:
$('#example').DataTable({
"ajax": {
"url": "<url-placeholder>",
"dataType": "json",
"cache": true, // this is to remove the '_' sent by datatables
"data": function(params) {
// Put additional parameters here
return params;
},
"dataSrc": function(result) {
var data = JSON.stringify(result.data);
console.log(data);
return data;
},
"columns": [
{ data: "_id" },
{ data: "name" },
{ data: "symbol" }
]
}
});
I have HTML like this
<table id="example">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Symbol</th>
</tr>
</thead>
</table>
The server returned this:
[{"_id":"5abdd8548d46ed03dcb0ce2c","name":"ABS-CBN","symbol":"ABS"},{"_id":"5abdd8548d46ed03dcb0ce2d","name":"AC PREF B2","symbol":"ACPB2"},{"_id":"5abdd8548d46ed03dcb0ce2e","name":"Asiabest Gorup","symbol":"ABG"},{"_id":"5abdd8548d46ed03dcb0ce2f","name":"AC PREF B1","symbol":"ACPB1"},{"_id":"5abdd8548d46ed03dcb0ce30","name":"Anchor Land","symbol":"ALHI"},{"_id":"5abdd8548d46ed03dcb0ce31","name":"Bogo Medellin","symbol":"BMM"},{"_id":"5abdd8548d46ed03dcb0ce32","name":"DAVINCI CAPITAL","symbol":"DAVIN"},{"_id":"5abdd8548d46ed03dcb0ce33","name":"FIRST METRO ETF","symbol":"FMETF"},{"_id":"5abdd8548d46ed03dcb0ce34","name":"IPeople","symbol":"IPO"},{"_id":"5abdd8548d46ed03dcb0ce35","name":"Manila Bulletin","symbol":"MB"}]
The datatables returning this error. And I have searched for answers for many hours now. I am stuck on this error
DataTables warning: table id=example - Requested unknown parameter '1' for row 0, column 1. For more information about this error, please see http://datatables.net/tn/4
I think the problem is because you have the columns definition within the Ajax block - it should be outside:
$('#example').DataTable({
"ajax": {
"url": "<url-placeholder>",
"dataType": "json",
"cache": true, // this is to remove the '_' sent by datatables
"data": function(params) {
// Put additional parameters here
return params;
},
"dataSrc": function(result) {
var data = JSON.stringify(result.data);
console.log(data);
return data;
}
},
"columns": [
{ data: "_id" },
{ data: "name" },
{ data: "symbol" }
]
});
I don't believe that the cache and dataType options are supported by DataTables, but try removing those after moving the columns block first.
Related
I have worked through various tutorials to understand and implement the Api Calls (Endpoints), defining Getters, almost to the point where I can fully invoke CRUD operations through routes pointing to them accordingly.
I can create Foreign Keys through sequelize, which creates my PostgreSQL table perfectly
async showAll (req, res) {
try {
const products = await Product.findAll({
where: {}
})
res.send(products)
} catch (err) {
res.status(500).send({
error: 'An Error has occured trying to retrieve Products'
})
}
},
In Postman
When hitting my endpoint GET /principals
All the relevant products are also displayed
{
"id": 2,
"name": "Company B",
"telephoneNumber": "012 111 1111",
"address": "Betha Str\nBedrasDorp",
"logo": "",
"registrationNumber": "2020/123/1234",
"taxNumber": "123",
"monthEnd": 1,
"createdAt": "2020-01-31T09:29:39.692Z",
"updatedAt": "2020-01-31T09:29:39.692Z",
"products": [
{
"id": 18,
"stockCode": "U7U5U",
"nappiCode": "NULL",
"barCode": "NULL",
"description": "Silver",
"sysPrice": 297.43,
"image": "",
"createdAt": "2020-01-31T09:25:22.620Z",
"updatedAt": "2020-01-31T09:25:22.620Z",
"principalId": 2
},
My question
How do I display my Principal Name in a Vue component and not just the principalID as per sequelize created column on my postgreSQL DB.
My current section within products.vue
<script>
....
async mounted () {
// do request to list all products
this.products = (await ProductsService.showAll()).data
}
...
</script>
displaying the productId
....
<template
slot="items"
slot-scope="{ item }">
<td>{{ item.stockCode }}</td>
<td>{{ item.description }}</td>
<td class="text-xs-left"> {{ item.principalId }} </td>
</template>
...
How can I display the Principal - name from a foreign key constraint? Linked in my PostgreSQL table in the Vue component.
Please help!
I managed to sort it out.
You controller section should include.
async showAll (req, res) {
try {
const products = await Product.findAll({
where: {},
include: [
{
model: ParentName
}
]
})
res.send(products)
} catch (err) {
res.status(500).send({
error: 'An Error has occured trying to retrieve Products'
})
}
}
Your .vue component Script section
async mounted () {this.products = (await ProductsService.showAll()).data
}
And calling it in the Template Component within vue becomes easy
{{ props.item.Principal.name }}
I have a Kendo UI Grid that is calling a rest service. It works fine, as long as I do not try to use any params.
I know the the rest service is correct, as I can call it from a browser, and get correct results [depending on the param I send]. Also, when I look the server log I see that it is calling the rest service with no params.
My code is below:
document).ready( function() {
var crudServiceBaseUrl = "rsPC.xsp",
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/PCByStatus",
filter: {field: "status", value: "2" }
dataType: "json",
update: {
url: crudServiceBaseUrl + "/PC/Update",
dataType: "json"
},
destroy: {
url: crudServiceBaseUrl + "/PC/Destroy",
dataType: "json"
},
create: {
url: crudServiceBaseUrl + "/PC/Create",
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
batch: true,
pageSize: 20,
scrollable: {
virtual: true
},
height: 543,
schema: {
model: {
id: "PCId",
fields: {
PCId: {type:"string"},
serialNumber: {type: "string"},
officeLoc: {type: "string"},
unid: {type:"string"},
model: {type:"string"},
checkInDate: {type: "string"}
}
}
}
});
// Grid
grid = $("#grid").kendoGrid( {
dataSource: dataSource,
columns : [ {
field : "serialNumber",
title : "Serial Number"
}, {
field : "model",
title : "Model"
}, {
field : "officeLoc",
title : "Office Location"
}, {
field : "checkInDate",
title : "Check In Date",
template: "#= kendo.toString(kendo.parseDate(checkInDate, 'yyyy-MM-dd'), 'MM/dd/yyyy') #"
} ],
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
dataBound : addExtraStylingToGrid,
reorderable : true,
filterable : true,
scrollable : true,
selectable : true,
sortable : true,
});
I still cannot get this to work and am a bit stumped.
I have two rest services, one returns all data, one takes "status" as a part and return a subset of the data that equals the parm.
The URL is:
http://localhost/scoApps/PC/PCApp.nsf/rsPC.xsp/PCByStatus?status=2
When entered into browser I get the correct number of records.
So I changed the code (see below). I have included all of the code for the CSJS:
$(document).ready( function() {
// Double Click On row
$("#grid").on(
"dblclick",
" tbody > tr",
function() {
var grid = $("#grid").data("kendoGrid");
var row = grid.dataItem($(this));
window.location.replace("xpFormPC.xsp" + "?key=" + row.unid + "target=_self");
});
// Add hover effect
addExtraStylingToGrid = function() {
$("table.k-focusable tbody tr ").hover( function() {
$(this).toggleClass("k-state-hover");
});
};
// Search
$("#search").keyup( function() {
var val = $('#search').val();
$("#grid").data("kendoGrid").dataSource.filter( {
logic : "or",
filters : [ {
field : "serialNumber",
operator : "contains",
value : val
}, {
field : "officeLoc",
operator : "contains",
value : val
}, {
field : "model",
operator : "contains",
value : val
} ]
});
});
var crudServiceBaseUrl = "rsPC.xsp",
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/PCByStatus",
dataType: "json"
},
update: {
url: crudServiceBaseUrl + "/PC/Update",
dataType: "json"
},
destroy: {
url: crudServiceBaseUrl + "/PC/Destroy",
dataType: "json"
},
create: {
url: crudServiceBaseUrl + "/PC/Create",
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation == "read"){
options.field = "status"
options.value = "2"
return options;
}
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
batch: true,
pageSize: 20,
scrollable: {
virtual: true
},
height: 543,
schema: {
model: {
id: "PCId",
fields: {
PCId: {type:"string"},
serialNumber: {type: "string"},
officeLoc: {type: "string"},
unid: {type:"string"},
model: {type:"string"},
checkInDate: {type: "string"}
}
}
}
});
// Grid
grid = $("#grid").kendoGrid( {
dataSource: dataSource,
columns : [ {
field : "serialNumber",
title : "Serial Number"
}, {
field : "model",
title : "Model"
}, {
field : "officeLoc",
title : "Office Location"
}, {
field : "checkInDate",
title : "Check In Date",
template: "#= kendo.toString(kendo.parseDate(checkInDate, 'yyyy-MM-dd'), 'MM/dd/yyyy') #"
} ],
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
dataBound : addExtraStylingToGrid,
reorderable : true,
filterable : true,
scrollable : true,
selectable : true,
sortable : true
});
// Edit
function onEdit(e) {
}
// Change
function onChange(args) {
var model = this.dataItem(this.select());
ID = model.ID;
}
;
});
What am I doing wrong?
=========================================
I have a workaround. Or possibly this is the way it is supposed to be done.
var crudServiceBaseUrl = "rsPC.xsp", dataSource = new kendo.data.DataSource(
{
transport : {
read : {
url : crudServiceBaseUrl
+ "/PCByStatus?status=2",
dataType : "json"
},
Now I just construct the URL I want. Not so elegant I suppose, but it works.
I have a workaround. Or possibly this is the way it is supposed to be done.
var crudServiceBaseUrl = "rsPC.xsp", dataSource = new kendo.data.DataSource(
{
transport : {
read : {
url : crudServiceBaseUrl
+ "/PCByStatus?status=2",
dataType : "json"
},
Filter is used for client side data unless you set serverFiltering to true.
Here is the filter kendo documentation and the serverFiltering documentation.
I use parameterMap when I need to send parameters that are not created by filtering the control that I'm using. The kendo documentation provides an example using parameterMap.
Here is an example of how I've used it in the past:
var appsDataSource = new kendo.data.DataSource({
transport: {
read: {
url: apiUrl + "App"
},
parameterMap: function (data, action) {
if (action === "read") {
data.lobid = lobId;
data.parent = isParent;
return data;
} else {
return data;
}
}
}
});
Try changing the parameterMap:
parameterMap: function(options, operation) {
if (operation == "read"){
options.field = "status";
options.value = "2";
return options;
}
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
and update the read definition to remove filter. One thing to consider is that you are not returning anything from the read method if it doesn't meet the criteria of not being a read and options is not null. That leaves out any other combination that isn't obviously handled in your existing code.
I'm evaluating OpenUI5 and I'm not clear about the binding concept.
In a XML login view, I have a Combobox that I want to populate after a successful login:
<ComboBox id="cboJoraniInstance" enabled="false" />
So, into my controller I've created an Ajax call with a parameter:
return Controller.extend("sap.ui.jorani.wt.controller.Login", {
onCheckEmail : function () {
var oDialog = this.getView().byId("BusyDialog");
oDialog.open();
var sMail = this.getView().byId("txtEmail").getValue();
var oListInst = this.getView().byId("cboJoraniInstance");
var aData = jQuery.ajax({
type : 'POST',
url : 'http://localhost/dummy/getJoraniInstances.php',
data: {
mail: sMail
},
async: false,
success : function(data,textStatus, jqXHR) {
//Link Combobox
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(data);
oListInst.setModel(oModel);
oListInst.bindElement("/Instances");
oListInst.bindProperty("value", "Url");
oListInst.bindProperty("name", "name");
oListInst.setEnabled();
},
error: function (jqXHR, textStatus, errorThrown){
MessageToast.show('An error occured');
}
});
oDialog.close();
},
});
The call to my web service is OK and returns:
{
"Instances": [{
"Name": "Local",
"IsDefault": true,
"Url": "http:\/\/localhost\/jorani\/"
}, {
"Name": "D\u00e9mo",
"IsDefault": false,
"Url": "https:\/\/demo.jorani.org\/"
}]
}
The code executes without error, but the control is not filled by my binding attempts.
I've checked the various SO questions on this topic and they all add a new ComboBox into the view dynamically, for example:
oListInst.placeAt("content");
But that is not what I want to achieve, I'd like to fill an existing object. Is it possible?
Concerning the view, if I fill the Combobox with the code below, it is working fine (but it doesn't use the binding feature):
$.each(data.Instances, function(i, obj) {
oListInst.addItem(new sap.ui.core.ListItem({key:obj.Url, text:obj.Name}));
});
i want to increase mongodb document number automatically using loopback.
I made function in mongo
function getNextSequence(name) {
var ret = db.counters.findAndModify(
{
query: { _id: name },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
db.tweet.insert(
{
"_id" : getNextSequence("userid"),
"content": "test",
"date": "1",
"ownerUsername": "1",
"ownerId": "1"
}
)
It is working in mongo shell.
However when I insert using loopback.js browser (http://localhost:3000/explorer/), It is not working.
400 error(SytaxError) code is showing.
I can not use mongo function in loopback rest API ?
I think problem is quotes in this line getNextSequence("userid"),
Create a collection counters with properties value and collection
{
"name": "counters",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {
"type": "number",
"collection": "string"
},
"validations": [],
"relations": {},
"acls": [
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
],
"methods": []
}
Now supposing your auto-increment collection name tweets.
Insert this value to counters.
{
"value" : 0,
"collection" : "tweet"
}
Now common/models/tweet.js
tweet.observe('before save', function (ctx, next) {
var app = ctx.Model.app;
//Apply this hooks for save operation only..
if(ctx.isNewInstance){
//suppose my datasource name is mongodb
var mongoDb = app.dataSources.mongodb;
var mongoConnector = app.dataSources.mongodb.connector;
mongoConnector.collection("counters").findAndModify({collection: 'tweet'}, [['_id','asc']], {$inc: { value: 1 }}, {new: true}, function(err, sequence) {
if(err) {
throw err;
} else {
// Do what I need to do with new incremented value sequence.value
//Save the tweet id with autoincrement..
ctx.instance.id = sequence.value.value;
next();
} //else
});
} //ctx.isNewInstance
else{
next();
}
}); //Observe before save..
I would love to add 1 more point to Robins Answer,you can add upsert:true so that it automatically creates the document if it doesn't exist
tweet.observe('before save', function (ctx, next) {
var app = ctx.Model.app;
//Apply this hooks for save operation only..
if(ctx.isNewInstance){
//suppose my datasource name is mongodb
var mongoDb = app.dataSources.mongodb;
var mongoConnector = app.dataSources.mongodb.connector;
mongoConnector.collection("counters").findAndModify({collection: 'tweet'}, [['_id','asc']], {$inc: { value: 1 }}, {new: true,upsert:true}, function(err, sequence) {
if(err) {
throw err;
} else {
// Do what I need to do with new incremented value sequence.value
//Save the tweet id with autoincrement..
ctx.instance.id = sequence.value.value;
next();
} //else
});
} //ctx.isNewInstance
else{
next();
}
}); //Observe before save..
You can do something like in this example for loopback 4
let last_record = await this.testRepository.findOne({order: ['id DESC']});
if(last_record) invoice.id = last_record.id+1;
This will generate your model with the property:
#property({
type: 'number',
id: true,
default: 1,
generated: false
})
id: number;
Hopefully, this helps, please write me if there is any other code. Thanks
If you want to use MongoDB operators directly in loopback methods you need to enable the option "allowExtendedOperators", you can do so on a per model basis or at the data source level (will apply to all models using the data source).
datasources.json:
"MongoDs": {
"host": "127.0.0.1",
"port": 27017,
"url": "mongodb://localUser:MYPASSWORD!#127.0.0.1:27017/test-database",
"database": "test-database",
"password": "MYPASSWORD!",
"name": "MongoDs",
"user": "localUser",
"useNewUrlParser": true,
"connector": "mongodb",
"allowExtendedOperators": true
},
While creating mixed chart in Zingchart we can pass the type attribute values with values array. But I'm not sure when reading data from CSV how this can be achieved.
I want to create mixed chart as on fiddle link below but data is to be read from a csv file.
var myConfig =
{
"type":"mixed",
"series":[
{
"values":[51,53,47,60,48,52,75,52,55,47,60,48],
"type":"bar",
"hover-state":{
"visible":0
}
},
{
"values":[69,68,54,48,70,74,98,70,72,68,49,69],
"type":"line"
}
]
}
zingchart.render({
id : 'myChart',
data : myConfig,
height: 500,
width: 725
});
<script src="https://cdn.zingchart.com/zingchart.min.js"></script>
<div id="myChart"></div>
I put together a demo for you using the sample data you provided in one of your related questions. If you go to this demo page and upload the CSV you originally provided, you should get this chart:
ZingChart includes a CSV parser for basic charts, but a more complex case like this requires a bit of preprocessing to get your data where it needs to be. I used PapaParse for this demo, but there are other parsing libraries available.
Here's the JavaScript. I'm using a simple file input in the HTML to get the CSV.
var csvData;
var limit = [],
normal = [],
excess = [],
dates = [];
var myConfig = {
theme: "none",
"type": "mixed",
"scale-x": {
"items-overlap":true,
"max-items":9999,
values: dates,
guide: {
visible: 0
},
item:{
angle:45
}
},
"series": [{
"type": "bar",
"values": normal,
"stacked": true,
"background-color": "#4372C1",
"hover-state": {
"visible": 0
}
}, {
"type": "bar",
"values": excess,
"stacked": true,
"background-color": "#EB7D33",
"hover-state": {
"visible": 0
}
}, {
"type": "line",
"values": limit
}]
};
/* Get the file and parse with PapaParse */
function parseFile(e) {
var file = e.target.files[0];
Papa.parse(file, {
delimiter: ",",
complete: function(results) {
results.data.shift(); //the first array is header values, we don't need these
csvData = results.data;
prepChart(csvData);
}
});
}
/* Process the results from the PapaParse(d) CSV and populate
** the arrays for each chart series and scale-x values
*/
function prepChart(data) {
var excessVal;
//PapaParse data is in a 2d array
for (var i = 0; i < data.length; i++) {
//save reference to your excess value
//cast all numeric values to int (they're originally strings)
var excessVal = parseInt(data[i][4]);
//date, limit value, and normal value can all be pushed to their arrays
dates.push(data[i][0]);
limit.push(parseInt(data[i][1]));
normal.push(parseInt(data[i][3]));
/* we must push a null value into the excess
** series if there is no excess for this node
*/
if (excessVal == 0) {
excess.push(null);
} else {
excess.push(excessVal);
}
}
//render your chart
zingchart.render({
id: 'myChart',
data: myConfig,
height: 500,
width: 725
});
}
$(document).ready(function() {
$('#csv-file').change(parseFile);
});