Laravel Yajra Datatables Hide Null Column - laravel-7

Wha is the best way to hide empty or null comumns from Yajra Datatables:
var table = $('.data-table').DataTable({
processing: true,
serverSide: true,
ajax: "{{ route('any.route') }}",
columns: [
// How to Hide any of these columns if its data is empty or null?
// for exampe I want to hide mname column ?
// visible: what condition for example !!!!
{data: 'fname', name: 'fname'},
{data: 'mname', name: 'mname'},
{data: 'lname', name: 'lname'},
....
]
});
How do I hide th in table whenever any data is empty or null. for instance, using visible:, what condition should I use to test if the data: is empty or null

Can I see your controller? I have same issue but I can fix it
Try this in your controller!
public function example(){
if ($request->ajax()) { // if request ajax
$data = User::all(); // take all user table
return Datatables::of($data)
->editColumn('fname', function ($row) { //this example for edit your columns if colums is empty
$fname = !empty($row->name) ? $row->name : 'empty';
return $fname;
})
->make(true);
return view('example', compact('data'));
}}

This is the best way to hide NULL values from the data tables.
$('#leads').DataTable({
"columnDefs": [{
"defaultContent": "-",
"targets": "_all"
}]

Related

Tabulator - Styling empty cells

I'm trying to style only tabulator empty cells.
I tried with a custom formatter but it seems to be called only on cells with data.
Any suggestion on how to proceed?
Seems to process fields without data just fine ...
https://jsfiddle.net/udpr2680/
new Tabulator("#tabulator", {
data:[{id:4957},{id:39857,price:100}],
columns: [
{ title: "number", field: "id"},
{ title: "price", field: "price",formatter: function(c,fP,onR) { let p = c.getData().price; if (p === undefined) return "undefined"; return p; } },
],
});

Node - Knex to return array of objects as a result of joined tables

I am using knexjs and node and running postgres db with this tables: menu and menuItem having one-to-many relationship. I found a solution here knex: what is the appropriate way to create an array from results? however this returns an array of strings. What i need is to return an array of objects and an empty array if null that looks exactly as the example below:
[
{
id: 123,
name: 'Sunday Menu',
items: []
},
{
id: 456,
name: 'Monday Menu',
items: [
{
id: 987,
name: 'Fried Chicken',
pcs: 69
},
{
id: 876,
name: 'Egg Soup',
pcs: 50
},
]
}
]
My menu and menuItem table schema looks similar to this:
menu_table: {
id,
name,
timestamps
}
menuItem_table: {
id,
menu_id,
name,
pcs,
timestamps
}
Currently, my code is like this:
knex('menu').leftJoin('menuitem', 'menu.id', 'menuitem.menu_id')
.select(['menu.id as menuID', knex.raw('ARRAY_AGG(menuitem.name) as items')])
.groupBy('menu.id')
And here's the result:
[
{
"menuID": "20091fff-ca8b-42d6-9a57-9f6e1922d0fa",
"items": [
null
]
},
{
"menuID": "2ddad4fa-7293-46c5-878f-cb2881be3107",
"items": [
"Fried Chicken",
"Egg Soup",
"Vegetable Dish"
]
}
]
UPDATE: I found out how to do it using raw query how ever i can't translate it using knex. Here's my code:
SELECT menu.*, COALESCE(menuitem.items, '[]') AS items FROM menu LEFT JOIN LATERAL (
SELECT json_agg(menuitem.*) AS items FROM menuitem WHERE menu.id = menuitem.menu_id
) menuitem ON true
I finally found a solution to my question. Since I was able to get my desired result thru raw query, i just translate it to knex. My final code is this:
const coalesce = knex.raw(`coalesce(menuitem.items, '[]') as items`)
const sub = knex('menuitem').select(knex.raw('json_agg(menuitem.*) as items')).whereRaw('menu.id = menuitem.menu_id')
return knex('menu').select(['menu.*', coalesce]).joinRaw('left join lateral ? menuitem on true', sub)
I'm gonna go with this code in the mean time until someone would give me the most accurate answer.
This work, im add attachments, ty DevWannabe :
const results = await knex.column({
'id': 'str.id',
'projectName': 'str.project_name',
})
.from('venturedoor.startups as str')
.leftJoin('venturedoor.attachments as att', 'str.id', 'att.startup_id')
// join array attachments
.select(['str.id', knex.raw('ARRAY_AGG(att.*) as attachments')])
.groupBy('str.id')
knex.raw('coalesce(usr.userName,usr.email ,seat.username) as username')
We can use like that measn. If userName is empty so will call email if email also then will call name from seats.

knex js query many to many

i'm having trouble with node & knex.js
I'm trying to build a mini blog, with posts & adding functionality to add multiple tags to post
I have a POST model with following properties:
id SERIAL PRIMARY KEY NOT NULL,
name TEXT,
Second I have Tags model that is used for storing tags:
id SERIAL PRIMARY KEY NOT NULL,
name TEXT
And I have many to many table: Post Tags that references post & tags:
id SERIAL PRIMARY KEY NOT NULL,
post_id INTEGER NOT NULL REFERENCES posts ON DELETE CASCADE,
tag_id INTEGER NOT NULL REFERENCES tags ON DELETE CASCADE
I have managed to insert tags, and create post with tags,
But when I want to fetch Post data with Tags attached to that post I'm having a trouble
Here is a problem:
const data = await knex.select('posts.name as postName', 'tags.name as tagName'
.from('posts')
.leftJoin('post_tags', 'posts.id', 'post_tags.post_id')
.leftJoin('tags', 'tags.id', 'post_tags.tag_id')
.where('posts.id', id)
Following query returns this result:
[
{
postName: 'Post 1',
tagName: 'Youtube',
},
{
postName: 'Post 1',
tagName: 'Funny',
}
]
But I want the result to be formated & returned like this:
{
postName: 'Post 1',
tagName: ['Youtube', 'Funny'],
}
Is that even possible with query or do I have to manually format data ?
One way of doing this is to use some kind of aggregate function. If you're using PostgreSQL:
const data = await knex.select('posts.name as postName', knex.raw('ARRAY_AGG (tags.name) tags'))
.from('posts')
.innerJoin('post_tags', 'posts.id', 'post_tags.post_id')
.innerJoin('tags', 'tags.id', 'post_tags.tag_id')
.where('posts.id', id)
.groupBy("postName")
.orderBy("postName")
.first();
->
{ postName: 'post1', tags: [ 'tag1', 'tag2', 'tag3' ] }
For MySQL:
const data = await knex.select('posts.name as postName', knex.raw('GROUP_CONCAT (tags.name) as tags'))
.from('posts')
.innerJoin('post_tags', 'posts.id', 'post_tags.post_id')
.innerJoin('tags', 'tags.id', 'post_tags.tag_id')
.where('posts.id', id)
.groupBy("postName")
.orderBy("postName")
.first()
.then(res => Object.assign(res, { tags: res.tags.split(',')}))
There are no arrays in MySQL, and GROUP_CONCAT will just concat all tags into a string, so we need to split them manually.
->
RowDataPacket { postName: 'post1', tags: [ 'tag1', 'tag2', 'tag3' ] }
The result is correct as that is how SQL works - it returns rows of data. SQL has no concept of returning anything other than a table (think CSV data or Excel spreadsheet).
There are some interesting things you can do with SQL that can convert the tags to strings that you concatenate together but that is not really what you want. Either way you will need to add a post-processing step.
With your current query you can simply do something like this:
function formatter (result) {
let set = {};
result.forEach(row => {
if (set[row.postName] === undefined) {
set[row.postName] = row;
set[row.postName].tagName = [set[row.postName].tagName];
}
else {
set[row.postName].tagName.push(row.tagName);
}
});
return Object.values(set);
}
// ...
query.then(formatter);
This shouldn't be slow as you're only looping through the results once.

React-Bootstrap-Table-Next Only One Row of Data in Table

I am trying to create a table for my website and for some reason it is only showing the first row of data.
This is how I am formatting the columns of the data:
const { items } = this.props.item;
// console.log({ items });
// react - bootstrap - table - next
const columns = [{
dataField: 'team',
text: 'Team',
sort: true,
formatter: (cellContent, row, rowIndex) => (
Object.values(row.team)[rowIndex]
)
}, {
dataField: 'current_Rank',
text: 'Current Rank',
sort: true,
formatter: (cellContent, row, rowIndex) => (
Object.values(row.current_Rank)[rowIndex]
)
}, {
dataField: 'new_Rank',
text: '321 Rank',
sort: true,
formatter: (cellContent, row, rowIndex) => (
Object.values(row.new_Rank)[rowIndex]
)
}];
This is how I am returning the table so that it renders the table:
return (
<BootstrapTable
keyField="team"
data={items}
columns={columns}
striped
hover />
)
}
}
The data:
Picture from the console
Live site: https://nhl-321-pointsystem.herokuapp.com/
I looked up your network response for /api/items API call, and found out that the data contains only one item. This being one of the reason you're seeing a single row when the table is rendered.
Please note the, another reason for the issue is, react-bootstrap-table-next key
data accepts a single Array object. And not array of single object.
You should re-arrange your data so that key 'team' will be present for all items in the array. And rest of the column header values (e.g. current_Rank) are available for each like.
Something like a reformat function I created in the sandbox available here.
Plus point - After you apply the reformat function, you won't need formatter for each column unlike your previous solution.
Alternate but recommended solution would be to send the formatted response from the API endpoint only, instead of re-parsing and creating new object to fit the needs of UI.
Sandbox link - https://codesandbox.io/embed/32vl4x4oj6

Kendo UI Grid search as type example

I would like to search datagrid in Kendo UI during typing into input field above the grid.
How can I do it?
Thanks for any advice.
Here is example of columns:
$("#grid").kendoGrid({
dataSource: dataPacket,
filterable: true,
pageSize: 10,
pageable: true,
sortable: true,
reorderable: true,
resizable: true,
columnMenu: true,
height: 550,
toolbar: ["create", "save", "cancel"],
columns: ["id",
"username",
"name",
"surname",
"email",
{
field :"created",
title : "Created at",
format: "{0:M/d/yyyy}",
parseFormats: ["dd-MM-yyyy"],
type: "date"
},
Kendo make this thing really easy for you, what is needed is to create a filter and pass it to the DataSource.
http://docs.telerik.com/kendo-ui/api/framework/datasource#methods-filter
However, this problem must be divided into two different tasks:
a) Capture the key events in the search box, throttle it and start the search "operation".
b) Build a filter and pass it to the DataSource.
So for throttling the keyboard events, we need a timeout. Or use the throttle function from underscorejs. Why? We don't wanna trigger a search operation on each key press. Only 250 milliseconds (this number is up to you) after the last keystroke.
Here is your sample HTML
<input type="text" id="search" />
Here is your sample script. I wrap everything as a self calling function as you don't wanna create a mess declaring global variables.
(function($, kendo){
// ID of the timeout "timer" created in the last key-press
var timeout = 0;
// Our search function
var performSearch = function(){
// Our filter, an empty array mean "no filter"
var filter = [];
// Get the DataSource
var dataSource = $('#grid').data('kendoGrid').dataSource;
// Get and clean the search text.
var searchText = $.trim($('#search').val());
// Build the filter in case the user actually enter some text in the search field
if(searchText){
// In this case I wanna make a multiple column search so the filter that I want to apply will be an array of filters, with an OR logic.
filter.push({
logic: 'or',
filters:[
{ field: 'username', operator: 'contains', value: searchText },
{ field: 'name', operator: 'contains', value: searchText },
{ field: 'surname', operator: 'contains', value: searchText },
{ field: 'email', operator: 'contains', value: searchText }
]
});
}
// Apply the filter.
dataSource.filter(filter);
};
// Bind all the keyboard events that we wanna listen to the search field.
$('#search').on('keyup, keypress, change, blur', function(){
clearTimeout(timeout);
timeout = setTimeout(performSearch, 250);
});
})(window.jQuery, window.kendo);
Bottom-line: Make sure you are using the right DataSource configuration.
If you configured serverFiltering = true, this filtering logic will be part of your Ajax request, so your server will have to interpret and perform the filtering on server-side.
In case you configured serverFiltering = false all this filtering logic will be evaluated on client side using JavaScript (damn fast!). And in this case, the schema (what data-type is expected on each column) must be also well-configured.

Resources