You can create a custom Table Type dedicated to AJAX-sourced data. This approach has the advantage of being totally reuasble, while the AJAX via data function may be less reuasble across multiple table instances.
The example bellow reuses 2 times the same logic, changing only the data
parameter to a different endpoint.
data
function. You may also want to debounce your data processing to avoid requests spamming.
import axios from 'axios';
import Vue from 'vue';
import { TColumnsDefinition, VuejsDatatableFactory } from 'vuejs-datatable';
import { colFieldToStr, formatUtcDate, ISpaceXLaunch, makeQueryStringFromObj } from '../utils';
VuejsDatatableFactory.registerTableType<any, any, any, any, any>( 'ajaxtable', tableType => tableType
.setFilterHandler( ( source, filter, columns ) => ( {
// See https://documenter.getpostman.com/view/2025350/RWaEzAiG#json-field-masking
filter: columns.map( col => colFieldToStr( col.field! ).replace( /\./g, '/' ) ).join( ',' ),
} ) )
.setSortHandler( ( endpointDesc, sortColumn, sortDir ) => ( {
...endpointDesc,
...( sortColumn && sortDir ? {
order: sortDir,
sort: colFieldToStr( sortColumn.field! ).replace( /\./g, '/' ),
} : {} ),
} ) )
.setPaginateHandler( ( endpointDesc, perPage, pageIndex ) => ( {
...endpointDesc,
...( perPage !== null ? {
limit: perPage || 10,
offset: ( ( pageIndex - 1 ) * perPage ) || 0,
} : {} ),
} ) )
// Alias our process steps, because the source, here, is our API url, and paged is the complete query string
.setDisplayHandler( async ( { source: baseEndPoint, paged: endpointDesc } ) => {
const url = `${ baseEndPoint }?${ makeQueryStringFromObj( endpointDesc ) }`;
const {
// Data to display
data,
// Get the total number of matched items
headers: { 'spacex-api-count': totalCount },
} = await axios.get<ISpaceXLaunch[]>( url );
return {
rows: data,
totalRowCount: parseInt( totalCount, 10 ),
};
} ) );
const app = new Vue( {
el: '#demo-app',
data: {
columns: [
{ label: 'Flight number', field: 'flight_number' },
{ label: 'Mission name', field: 'mission_name' },
{ label: 'Launch date', field: 'launch_date_utc', representedAs: row => formatUtcDate( new Date( row.launch_date_utc ) ) },
{ label: 'Rocket type', field: 'rocket.rocket_name', sortable: false },
{ label: 'Launch site', field: 'launch_site.site_name_long', sortable: false },
{
field: 'links.mission_patch_small',
interpolate: true,
label: 'Mission patch',
representedAs: row => row.links.mission_patch_small ?
`<img src="${ row.links.mission_patch_small }" alt="${ row.mission_name } patch" style="height: 6em;"/>` :
`<img src="https://www.gvmc.gov.in/wss/images/noimageavailable.png" alt="No patch for mission "${ row.mission_name }" available" style="height: 6em;"/>`,
sortable: false,
},
{
field: 'links.reddit_campaign',
interpolate: true,
label: 'Reddit link',
representedAs: row => `<a href="${ row.links.reddit_campaign }">${ row.mission_name } Reddit thread</a>`,
sortable: false,
},
] as TColumnsDefinition<ISpaceXLaunch>,
page: 1,
apiUrlPast: 'https://api.spacexdata.com/v3/launches/past',
apiUrlUpcoming: 'https://api.spacexdata.com/v3/launches/upcoming',
},
} );
<div id="demo-app">
<div class="row">
<div class="col-xs-12 table-responsive">
<h3>Past launches</h3>
<ajaxtable :columns="columns" :data="apiUrlPast" name="pastLaunches" :per-page="10"></ajaxtable>
<datatable-pager table="pastLaunches"></datatable-pager>
</div>
<div class="col-xs-12 table-responsive">
<h3>Upcoming launches</h3>
<ajaxtable :columns="columns" :data="apiUrlUpcoming" name="upcomingLaunches" :per-page="10"></ajaxtable>
<datatable-pager table="upcomingLaunches"></datatable-pager>
</div>
</div>
</div>
Generated using TypeDoc