Angular-datatables server-side processing and Buttons extension. data is empty - angular-datatables

use Angular4 and angular-datatables.
Everything looks fine (pagination, column sorting, export buttons), but when I try to print/copy/export a table, it only outputs the headers, even though the rest of the data is there.
Any ideas what's should I check?
this.dtOptions = {
pagingType: 'full_numbers',
pageLength: 20,
serverSide: true,
processing: true,
ajax: (dataTablesParameters: any, callback) => {
this.service.getServerSidePaganated(dataTablesParameters).subscribe(resp => {
that.cdrs = resp.data;
callback({
recordsTotal: resp.recordsTotal,
recordsFiltered: resp.recordsFiltered,
data: []
});
});
},
columns: [
{ data: 'source' },
{ data: 'destination' },
{ data: 'dateTime'},
{ data: 'callTime'},
{ data: 'timeOnHold'},
{ data: 'disposition'},
{ data: 'recordingFileName'}
],
// Declare the use of the extension in the dom parameter
dom: 'Bfrtip',
// Configure the buttons
buttons: [
'print',
'excel'
]
};
}

you should set the callback data
ajax: (dataTablesParameters: any, callback) => {
this.service.getServerSidePaganated(dataTablesParameters).subscribe(resp => {
// that.cdrs = resp.data; // remove this line
callback({
recordsTotal: resp.recordsTotal,
recordsFiltered: resp.recordsFiltered,
data: resp.data // set data
});
});

Related

Fastify validate schema with yup - schema.validateSync is not a function

From the Fastify documentation in the section titled Using other validation libraries I'm trying to get yup to validate my schema but I keep getting schema.validateSync is not a function and I don't know why??
I want the schema to still be valid for creating the swagger document but I want to use yup to give me the validation I need.
const yup = require("yup");
const yupOptions = {
strict: false,
abortEarly: false,
stripUnknown: true,
recursive: true,
};
async function isUsernameAvailable(fastify: any, _options: Object) {
const users = fastify.mongo.db.collection("users");
fastify.get(
"/api/v1/onboarding/isUsernameAvailable/:username",
{
schema: {
params: {
type: "object",
properties: {
username: { type: "string", maxLength: 12, minLength: 1 },
},
required: ["username"],
},
response: {
200: {
type: "object",
properties: {
available: {
type: "boolean",
description: "Returns true if username is available",
},
},
},
},
},
validatorCompiler: ({ schema, method, url, httpPart }: any) => {
return function (data: any) {
try {
const result = schema.validateSync(data, yupOptions);
return { value: result };
} catch (e) {
return { error: e };
}
};
},
},
async (request: any, _reply: any) => {
const { username } = request.params;
const foundNUsernames = await users.countDocuments(
{ username },
{ limit: 1 }
);
const available: boolean = foundNUsernames === 0;
return { available };
}
);
}
export { isUsernameAvailable };
if I use the below, the validation works but the swagger doc doesn't build
schema: {
params: yup.object({
username: yup.string().lowercase().max(12).min(1).required(),
}),
}
if I remove the validatorCompiler then I get no errors, swagger does build but I cant use yup
validatorCompiler: ({ schema, method, url, httpPart }: any) => {
return function (data: any) {
try {
const result = schema.validateSync(data, yupOptions);
return { value: result };
} catch (e) {
return { error: e };
}
};
},
}
how can I satisfy both?
Why do I want to use yup? I want to validate emails and transform values into lowercase.

How to use Custom HTTP request and paginations, sort, search in Vue 2.x

I am an engineer who makes web systems in Tokyo.
I'm making a search system using Grid.js, but I faced a problem.
I don't know the solution because it's not in the documentation.
Since this system uses Vue 2.x, it uses axios.post with Custom HTTP Requset.
I was able to get the list, but I'm having trouble implementing sorting, pagination, and keyword search.
I want to send parameters by Post request.
Please tell me how to implement this.
The code is below
data() {
return {
columns: [
{name: 'user name', id: 'user_name'},
{name: 'email', id: 'email'},
],
page: {
enabled: true,
limit: 100,
server: {
body: (prev, page) => {
console.log(page) // OK, show page number 0,1,2...
return {
page: page
}
}
},
},
sort: {
},
search: {
server: {
// url: (prev, keyword) => `${prev}?q=${keyword}`
// what's this.
}
},
server: {
url: '/api/v2/users/list',
method: 'POST',
async data (opt) {
let response = await axios.post(opt.url)
return {
data: response.data.results.map(item => {
return {
username: item.username,
email: item.email,
}
}),
total: response.data.count,
}
}
},
};
OK.
Set POST payload this.
data() {
return {
columns: [
{name: 'user name', id: 'user_name'},
{name: 'email', id: 'email'},
],
page: {
enabled: true,
limit: 100,
server: {
body: (prev, page) => {
console.log(page) // OK, show page number 0,1,2...
return {
page: page
}
}
},
},
sort: {
},
search: {
server: {
// url: (prev, keyword) => `${prev}?q=${keyword}`
// what's this.
}
},
server: {
url: '/api/v2/users/list',
method: 'POST',
body: {},
async data (opt) {
let response = await axios.post(opt.url)
return {
data: response.data.results.map(item => {
return {
username: item.username,
email: item.email,
}
}),
total: response.data.count,
}
}
},
};

How to implement a PUT request in Vue 3

I am trying to implement a PUT request to the https://crudcrud.com/ REST API.
I have a list of users and when I click an update button, I would like to show a modal and allow the user to update any of the fields (name, email, image URL). The main concern is that I am struggling with how to format the PUT request.
This is my current solution
// template (UserCrud.vue)
<button #click="update(user._id)">Update</button>
// script
components: { Create },
setup() {
const state = reactive({
users: [],
})
onMounted(async () => {
const { data } = await axios.get(`/users`)
state.users = data
})
async function update(id) {
await axios.put(`/users/${id}`)
state.users = ???
}
return { state, destroy, addUser }
Here is some sample data:
[
{
"_id": "6012303e37711c03e87363b7",
"name": "Tyler Morales",
"email": "moratyle#gmail.com",
"avatar": "HTTP://linkURL.com
},
]
For reference, this is how I create a new user using the POST method:
export default {
components: { Modal },
emits: ['new-user-added'],
setup(_, { emit }) {
const isModalOpen = ref(false)
const state = reactive({
form: {
name: '',
email: '',
avatar: '',
},
})
async function submit() {
const { data } = await axios.post('/users', state.form)
emit('new-user-added', data)
state.form.email = ''
state.form.name = ''
state.form.avatar = ''
isModalOpen.value = false
}
return { isModalOpen, submit, state }
},
}
Check this repo for the complete repo: the files are UserCrud.vue & Create.vue
You should pass the user object as parameter then send it as body for the put request by setting the id as param :
<button #click="update(user)">Update</button>
...
async function update(user) {
let _user={...user,name:'Malik'};//example
await axios.put(`/users/${user._id}`,_user);
const { data } = await axios.get(`/users`)
state.users = data
}
You could use the same code of adding new user for the update by defining a property called editMode which has true in update mode and based on this property you could perform the right request
export default {
components: { Modal },
emits: ['new-user-added','user-edited'],
props:['editMode','user'],
setup(props, { emit }) {
const isModalOpen = ref(false)
const state = reactive({
form: {
name: '',
email: '',
avatar: '',
},
})
onMounted(()=>{
state.form=props.user;//user to edit
})
async function submit() {
if(props.editMode){
const { data } = await axios.put('/users/'+props.user._id, state.form)
emit('user-edited', data)
}else{
const { data } = await axios.post('/users', state.form)
emit('new-user-added', data)
state.form.email = ''
state.form.name = ''
state.form.avatar = ''
}
isModalOpen.value = false
}
return { isModalOpen, submit, state }
},
}

In Falcor how to work with database?

I am new to falcor data fetching framework. I tried with few example when I request for something like
model.get(["contacts", {0..2}, "name"])
.then(response => {
this.state.list = response.json.contacts;
this.setState(this.state);
});
at server side
let data = {
contacts: [
{name: "ABC"},
{name: "XYZ"},
{name: "PQR"}
]
};
let contactsRouter = Router.createClass([
{
route: 'contacts[{integers:contactIndexes}]',
get: (pathSet) => {
let results = [];
pathSet.contactIndexes.forEach(contactIndex => {
if (data.contacts.length > contactIndex) {
results.push({
path: ["contacts", contactIndex, "name"],
value: data.contacts[contactIndex].name
});
}
});
return results;
}
},
{
route: 'contacts.add',
call: (callPath, args) => {
var newContact = args[0];
data.contacts.push({name: newContact})
return [
{
path: ['contacts', data.contacts.length-1, 'name'],
value: newContact
},
{
path: ['contacts', 'length'],
value: data.contacts.length
}
]
}
}
]);
I'm getting data & able to do other operations too.
My question is I want to do same CRUD operations with MongoDB instead from
data.contacts
how i construct JSON Graph object data should come from database schema. hope my question is cleared.
The simplest way is to simply do a database query inside the route's get function:
{
route: 'contacts[{integers:contactIndexes}]',
get: (pathSet) => {
const data = db.get('myModel', (err, res) => {
return res
})
let results = [];
pathSet.contactIndexes.forEach(contactIndex => {
if (data.contacts.length > contactIndex) {
results.push({
path: ["contacts", contactIndex, "name"],
value: data.contacts[contactIndex].name
});
}
});
return results;
}
}
Made a simple repo using Falcor and CouchDB. It should be enough to understand how it should be done in MongoDB.

Ext TreePanel: How to add Child Nodes to the expanded node?

I am trying to create a Tree from Ext.tree.Panel with JSON data.
My JSON
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
I want the first level nodes to be the "firstName: from the above JSON. I am able to achieve this but when any of the node is expanded the same nodes are displayed as children to the expanded node shown below.
- John
---> + John
---> + Anna
---> + Peter
+ Anna
+ Peter
When any of the node is expanded I want to add children from another JSON file. but here the problem is before adding the children to the node i can see the child nodes attached as above.
Is there any way to avoid this behavior ?
Code Snippet
My TreePanel:
Ext.define('MyApp.view.MyTreePanel', {
extend: 'Ext.tree.Panel',
height: 439,
width: 400,
title: 'My Tree Panel',
store: 'MyTreeStore',
displayField: 'firstName',
rootVisible: false,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
viewConfig: {
}
});
me.callParent(arguments);
}
});
TreeStore:
Ext.define('MyApp.store.MyTreeStore', {
extend: 'Ext.data.TreeStore',
requires: [
'MyApp.model.MyModel'
],
constructor: function(cfg) {
var me = this;
cfg = cfg || {};
me.callParent([Ext.apply({
autoLoad: true,
autoSync: true,
model: 'MyApp.model.MyModel',
storeId: 'MyTreeStore',
proxy: {
type: 'ajax',
url: 'employees.json',
reader: {
type: 'json',
root: 'employees'
}
}
}, cfg)]);
}
});
**Model:**
Ext.define('MyApp.model.MyModel', {
extend: 'Ext.data.Model',
fields: [
{
name: 'firstName'
}
]
});
Thanks in advance....
The url will get called for every node you click on that hasn't been 'loaded' yet. I'm not sure why ExtJS does this as the parameters change per node clicked. What I've done because I needed a lot of extra functionality is override the load() in the tree.Store (sorry, it's a little messy and could use a cleanup):
Ext.define('MyApp.store.MyTreeStore', {
extend: 'Ext.data.TreeStore',
load: function(options) {
options = options || {};
options.params = options.params || {};
var me = this,
node = options.node || me.tree.getRootNode(),
root;
// If there is not a node it means the user hasnt
// defined a rootnode yet. In this case lets just
// create one for them.
if (!node) {
node = me.setRootNode({
expanded: true
});
}
if (me.clearOnLoad) {
node.removeAll();
}
Ext.applyIf(options, {
node: node
});
options.params[me.nodeParam] = node ? node.getId() : 'root';
if (node) {
node.set('loading', true);
}
var root = me.getRootNode();
if (node.isRoot()) {
// put some root option.params here.
// otherwise, don't pass any if you don't need to
} else {
options.params = Ext.JSON.encode({
// or some parameter here for the node to
// get back the correct JSON data
nodeId: node.get('id')
});
}
return me.callParent([options]);
},
model: 'MyApp.model.MyModel',
storeId: 'MyTreeStore',
proxy: {
type: 'ajax',
url: 'employees.json',
reader: {
type: 'json',
root: 'employees'
}
},
autoLoad: false,
listeners: {
append: function(store,node,index) {
// on append depth 1 is first level, beforeappend it is 0
if (node.get('depth') == 1) {
// setting these values here assures that the node knows it's been loaded already.
// node.set('leaf',true); force leaf true, false or whatever you want.
node.set('loaded',true);
node.commit();
}
}
}
});
Also, you can do something like this to your JSON if you need to have the expand / collapse icons there. These are default fields that get added by default.
{
"employees": [
{ "firstName":"John" , "lastName":"Doe", leaf: false, children: []},
{ "firstName":"Anna" , "lastName":"Smith", leaf: false, children: []},
{ "firstName":"Peter" , "lastName":"Jones", leaf: false, children: []}
]
}