vincjo / datatables Goto Github PK
View Code? Open in Web Editor NEWA toolkit for creating datatable components with Svelte
Home Page: https://vincjo.fr/datatables
License: MIT License
A toolkit for creating datatable components with Svelte
Home Page: https://vincjo.fr/datatables
License: MIT License
I'm trying to filter by 'bios' which is nested in the hw-info key. I'm not sure how to do it, I've tried setting the filter key to item['hwinfo'] and item.hwinfo
with no luck. Is this possible?
item = { "id": "test-id", "hwinfo": { "bios": "3.4" } }
I know that I can filter with hwinfo
and search for 3.4, however I will have more fields in the object and some fields may have 3.4 in them as well.
First of all, thank you for this great package. It's easy to use and headless, making it a piece of cake to integrate into existing templates. I'm making a slightly different filter than your example. My Filter is inside a modal and there are many types of it, select, date, etc. I'm able to implement them all, but I don't have any way to tell the user if the current table is filtered. I would like to display the number of filters applied to the current table. Does Svelte Datatables provide this or is there any JavaScript code that works for this? Thank you.
It'd also be best if there's an option to override the messages other than the internationalization.
An example would be awesome!
eg. the Pagination Component has no class whatsoever.
Would be cool if Components could be written in this way too:
<Pagination
class="dt_pagination"
handler={ dataTable }
/>
Inside of the Component it can be done in this way:
<section class="{ if $$props.class !== undefined ? $$props.class : '' }">
Don't know if this is the official way, but i found it on the webs and it was very useful for me.
Is there any change of getting these added? Seeing as they can be optional it shouldn't break compatibility.
Apologies, I'm short on time and can't really provide a PR
Hi there, and thanks for your support.
In https://github.com/vincjo/datatables/blob/master/src/lib/core/Context.ts, the method createFilteredRows
uses stringMatch
to filter relevant rows. We (me and @rkpasia, working on https://github.com/fractal-analytics-platform/fractal-web) would be interested in replacing stringMatch
with a custom method. The reason for this is that we would like to select all rows where a certain column has a specific value.
Our use case is that (for instance) we have a column "ID", and rows with values 1, 2, ..., 10, 11, 12. We would like to be able to select the row with ID=1, without including the other IDs that match with 1 (e.g. 10 and 11). However, we don't see a way to achieve it with the current datatables. We could write a custom function, like
private stringExactMatch(entry:string|Object, value: string)
{
return entry === value
}
but we could not use this comparison function instead of stringMatch
.
If there exists a way to achieve this, and we missed it, suggestions are welcome! :)
Would you consider including the possibility of overriding the stringMatch
method as part of the Context
class?
How could this be exposed through the API, so that a user could replace stringMatch
with a custom function? Could it be a comparisonFunction
(undefined, by default) of Filters
?
If this sounds interesting, we could try setting up a PR.
I am looking for a proper way of styling all the components to my needs. This was an issue with Issue #29, but I am struggling to get this working.
It seems that there is ongoing debate in the svelte community how to pass CSS classes or whatsoever to child components. There are so many approaches with flaws etc.
I've found a very interesting and recent video - This Week in Svelte (2023 June 9) - Updates, Self-hosting SvelteKit, Passing styles to children - https://youtu.be/OG70PKD0hEU?t=2836.
My ultimate goal is to style the Datatable component from the outside by overwriting the built-in CSS attributes.
Of course, I could create my own Datatable components and regain full control over styling, but once you update the components and I would have to repeat the whole process. That would be cumbersome overall, I think.
Hoping for some support and suggestions :)
Thanks
Hello!
This was already mentioned in Issue #14, but it would be very helpful if styling could be applied to different components (Pagination, Search, RowsPerPage, ThFilter etc) without remaking all of those components.
The project I'm working on uses the Skeleton UI toolkit. The developers of Skeleton suggested using your datatable as a great replacement to what they are intending to make (since they have not implemented theirs yet), but currently, on a project with a dark background design, this datatable component is very hard to work with - I would have to remake many things from scratch just to change the font color to something readable.
Thanks!
Not sure if I'm missing something, but how do you remove any applied filters?
For example, I'm not using the table headers/input field to filter data - but programmatically using radio buttons, and so I need to be able to programmatically reset the filters
Hi man
First of all, I'd like to say this is an awesome project!
But I am just wondering if you have any plans to introduce some mobile-friendly features to the project,
like this one for instance Jquery DataTable Responsive Extension
In the following scenario, the filter is still applied, but the value is not displayed:
Some help will be appreciatted. Maybe some public method in Filters.ts to access the value of each filter or something like that...
Thanks in advance!
Is there any way to change the visibility of a column? I'm working with about 5 columns, and would like to hide 2 of them when the screen with is reduced to mobile/tablet size.
I seem to be able to pass class into the Th components, but CSS display: none
doesn't apply for some reason.
Hey, first of all thanks for the great package, it has worked out great so far.
But I recently stumbled onto a smallish issue.
I have tables and columns with filtering, and filtering numbers does work from 1-9 but not if it gets higher.
For example I have these data rows with values: AVG8, AVG10, AVG11
The filtering works like that:
AVG8, AVG11, AVG10 OR AVG10, AVG11, AVG8
Meaning it's only taking into consideration the first part, not the whole number.
I also attached some images to understand it better.
Can i sort/orderBy datatable with null values? it seems like it is not possible but i might be missing something here
Docs mention that we can set scope to currentPage,
When trying out row selection example and passing handlers selectAll method object { selectBy: "id", scope: "currentPage" }
and testing it out, it seems like it is not working as expected.
Try clicking on Th checkbox and switching pages, or deselecting checkbox on single row it seems like it doesn't update as expected.
What fixed it for me was:
changed ca line 35 of Context.js
from
return Object.keys(row).some(k => {
return row[k]
.toString()
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.indexOf($globalFilter
.toString()
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")) > -1;
});
TO
return Object.keys(row).some(k => {
if(row[k] !== null) {
return row[k]
.toString()
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.indexOf($globalFilter
.toString()
.toLowerCase()
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")) > -1;
} else {
return '';
}
});
is there a way to intervene witrh the search functionality? like the filter function ....
src/lib/local/Datatable.svelte:
3
4: type T = $$Generic
5
src/lib/local/Pagination.svelte:
3
4: type T = $$Generic
5
src/lib/local/RowCount.svelte:
3
4: type T = $$Generic
5
src/lib/local/RowsPerPage.svelte:
3
4: type T = $$Generic
5
src/lib/local/Search.svelte:
3
4: type T = $$Generic
5
src/lib/local/Th.svelte:
3
4: type T = $$Generic
5
src/lib/local/ThFilter.svelte:
3
4: type T = $$Generic
5
src/lib/remote/Datatable.svelte:
3
4: type T = $$Generic
5
src/lib/remote/Pagination.svelte:
3
4: type T = $$Generic
5
src/lib/remote/RowCount.svelte:
3
4: type T = $$Generic
5
src/lib/remote/RowsPerPage.svelte:
3
4: type T = $$Generic
5
src/lib/remote/Search.svelte:
3
4: type T = $$Generic
5
src/lib/remote/Th.svelte:
3
4: type T = $$Generic
5
src/lib/remote/ThFilter.svelte:
3
4: type T = $$Generic
5
src/routes/(local)/test/search-scope/Search.svelte:
3
4: type T = $$Generic
5
type T = $$Generic<Row>
export let handler: DataHandler<T>
What is $$Generic
for?
Why its not:
export let handler: DataHandler<Row>
Directly without the T?
Hello,
My application has 4 tabs on 1 page, you can imagine it like Gmail, where in the Inbox it has Primary, Promotion, and Socials. After implementing the Sort function, the data on each tab either becomes exactly the same or completely disappears. If the initial is the same data on each tab, then after reload the data will disappears on each tab, and vice versa. Here are the screenshots of the problem:
Same data on each tab:
Data disappears on each tab:
Here are the codes I'm using:
TableSort.svelte :
<script>
export let handler;
export let orderBy = null;
const identifier = orderBy?.toString();
const sorted = handler.getSort();
</script>
<th on:click={() => handler.sort(orderBy)} class:active={$sorted.identifier === identifier}>
<div class="d-flex align-items-center">
<slot />
<span class:asc={$sorted.direction === 'asc'} class:desc={$sorted.direction === 'desc'}></span>
</div>
</th>
<style>
th {
background: inherit;
cursor: pointer;
margin: 0;
padding: 14px 20px;
user-select: none;
}
th span {
margin-top: -2.5px;
padding-left: 8px;
}
th span::before,
th span::after {
border: 4px solid transparent;
content: '';
display: block;
width: 0;
height: 0;
margin-top: 2px;
}
th span::before {
border-bottom-color: #e0e0e0;
}
th span::after {
border-top-color: #e0e0e0;
}
th.active span.asc::before {
border-bottom-color: #6e7891;
}
th.active span.desc::after {
border-top-color: #6e7891;
}
</style>
Index.svelte (the same for Published, Drafts, and Trash):
<script>
import { DataHandler } from '@vincjo/datatables';
import TableSort from '../../Components/TableSort.svelte';
const handler = new DataHandler(productsAndSolutions, { rowsPerPage: 10 });
const rows = handler.getRows();
$: productsAndSolutions, handler.setRows(productsAndSolutions);
</script>
<TableSort {handler} orderBy="system" class="white-space-nowrap align-middle ps-4" scope="col" style="width: 350px;">SYSTEM</TableSort>
Is this a bug or there is something wrong with my code? Thank you.
In my data I have
{"id":1}
when i search 1 in filter or globa search, it doesn't work, and when i clear inputs it empties the table until I search for string.
Hello, I'm using clearFilters and while it works cleaning all the filters applied, it doesn't really reset the select for that filter. For example, after I run clearFilters function, my select still shows the selected filter (but the data change to no filter tho). I do have a wayaround this problem for now, like this:
function clearFilters() {
handler.clearFilters();
document.getElementById('starred').selectedIndex = '0';
document.getElementById('featured').selectedIndex = '0';
document.getElementById('published_at').selectedIndex = '0';
}
But it's extremely inefficient and it's not reusable as well since every page will have different filter. Is there any way to clear the filter while at the same time reseting any input or select that is used for that filter? Thank you.
Even though getSorted() is unchanged and returns the sorting object, the rows aren't sorted when the data is refresh
I'm thinking for the "items per page" selector, which sticks out a bit.
Hello
I get an error when there is no record.
---------------handler---------------------------
{"context":{"event":{"events":{"change":[],"clearFilters":[],"clearSearch":[]},"triggerChange":{}},"rowsPerPage":{},"pageNumber":{},"search":{},"filters":{},"filterCount":{},"rawRows":{},"filteredRows":{},"pagedRows":{},"rowCount":{},"pages":{},"pagesWithEllipsis":{},"pageCount":{},"sort":{},"selected":{},"selectScope":{},"isAllSelected":{}},"sortHandler":{"rawRows":{},"event":{"events":{"change":[],"clearFilters":[],"clearSearch":[]},"triggerChange":{}},"sort":{},"backup":[]},"selectHandler":{"filteredRows":{},"pagedRows":{},"selected":{},"scope":{},"isAllSelected":{},"event":{"events":{"change":[],"clearFilters":[],"clearSearch":[]},"triggerChange":{}}},"pageHandler":{"pageNumber":{},"rowCount":{},"rowsPerPage":{},"event":{"events":{"change":[],"clearFilters":[],"clearSearch":[]},"triggerChange":{}}},"searchHandler":{"search":{},"event":{"events":{"change":[],"clearFilters":[],"clearSearch":[]},"triggerChange":{}}},"filterHandler":{"filters":{},"event":{"events":{"change":[],"clearFilters":[],"clearSearch":[]},"triggerChange":{}}},"i18n":{"search":"Search...","show":"Show","entries":"entries","filter":"Filter","rowCount":"Showing {start} to {end} of {total} entries","noRows":"No entries found","previous":"Previous","next":"Next"}}
TypeError: $filteredRows.slice is not a function
Thank you for the amazing and elegant work!
My use case, involves having a headless CMS that provides api to access, paginate, filter and sort the data. The number of data rows is in the millions and hence can not be pre-fetched.
I was wondering if it is easy to connect datatables with arbitrary backend api (so the data is not all readily available) where we can retrieve the data for each page and apply any necessary filtration / sorting. All done for a backend api.
Should I, with my case above, implement/extend DataHander class?
I have tag categories that are each their own column, for example department and job level. I want to have an advanced filter for each column and have the filters work together, for example (department = product OR design) AND (job level = senior). If I manually define the filters with unique filter functions they work as expected. If I give them the same filter function or I create them dynamically (which I need to do) they work individually but not together with the other filters, it's the same behaviour as removing the other filters first.
Works ✅
const departmentFilter = handler.createAdvancedFilter((row) =>
row.tags.filter((x) => x.tagCategoryId === 1).map((x) => x.tagId),
);
const levelFilter = handler.createAdvancedFilter((row) =>
row.tags.filter((x) => x.tagCategoryId === 2).map((x) => x.tagId),
);
Doesn't work ❌
const filterFns = [1, 2].map((tagCategory) =>
handler.createAdvancedFilter((row) =>
row.tags.filter((x) => x.tagCategoryId === tagCategory).map((x) => x.tagId),
),
);
Doesn't work ❌
const departmentFilter = handler.createAdvancedFilter((row) =>
row.tags.map((x) => x.tagId),
);
const levelFilter = handler.createAdvancedFilter((row) =>
row.tags.map((x) => x.tagId),
);
Because the sorting only recalls the last sorted column, it can lead to rows jumping around when loading fresh data with setRows
. This occurs when the most recent sorted column has many rows with identical values and previously sorting by another column. After setRows
the table only recalls a single column of the sort order which may not produce the same sort as is currently displayed, causing some rows to jump. (sorry if this is a bit difficult to explain...)
You can see this in action here https://stackblitz.com/edit/vitejs-vite-xre2jw?file=src%2Flib%2FCounter.svelte
Steps:
These steps are a bit finicky sometimes it resets from descending and sometimes from ascending. You can more easily reproduce at https://prun.josephmr.dev/orders/HLS sort by "UNITS" then wait roughly 10 seconds for the data to refresh.
I'm unsure the best method for resolving this. My main thought would be to store more than just the last column sort, but store the last N column sorts where N <= number of columns.
First - I Love this datatable and thank you for all the support.
Is there a way to do either of the following:
Would be nice to be able to disable these feature by config !
in my particular case i don't need it so i masked it by CSS ...
Also had trouble figuring how to use reactivity using $: handler.setRows(data) ... maybe you can add a example in the docs !
On the whole pretty usefull library. Starred :)
the predecessor could do that ...
I've discovered an issue where if setRows() is used to apply new data the contents of the getSorted store goes from this (for example):
{identifier: 'Supplier Name', direction: 'asc', fn: ƒ}
to this:
{identifier: '(row) => row[orderBy]', direction: 'asc', fn: ƒ}
The data in the table itself is sorted correctly, but visually (the component) no longer displays the correct sorting direction (based on your example)
Hey!
This project is great make good data tables fast and im using it in a few of my projects which are in german but every text of the data table is english.. Is there some way to change that without really changing the actual source code ( because that would mean that people would have to make the same changes when downloading my project.. ) or is there already some functionality I did not know of?
Hi,
I am currently implementing this library in a project of mine. First of all great work!
I am trying to make the header and "footer" sticky, but in the documentation the sample code of “basic” and “sticky” is the same (also confirmed it in the SvelteKit code, the file is always the same).
The CSS under “tips” also does not work for me.
It would be wonderful if you could explain how the sticky header and footer is meant to be implemented.
Thank you in advance
I'm wondering if it's possible to have datatables have rowId & selected as internal variables for each row.
It would certainly help with handling dynamic data that may change it's original id and also ease the burden of stapling together selection functionality.
I've poked around the source code and if I understand it correctly, it should be possible but I might be misunderstanding how it works:
The only issue I saw is how you implement rowId given the Row class is supposed to hold internal state/variables.
Can we build a simple datatable from the json object below (with only some parts like "purchases") ?
As for now, it seems that the datahandler only accepts json arrays but not json objects.
const handler = new DataHandler(someData, { rowsPerPage: 50 })
// json example taken from https://www.customer.io/docs/json-in-segments/
someData = {
"last_shopped": 1662587234,
"location": {"city": "Montreal","province": "QC"},
"purchases": [
{
"id": 123,
"type": "computers",
"name": "Monitor",
"price": 25,
"discount": 10,
"shipping_address": {"city": "Calgary","province": "AB"},
"coupons_applied": [
{
"coupon_code": "AXXXXX",
"discount": "10%"
},
{
"coupon_code": "BXXXXX",
"discount": "15%"
}
]
},
{
"id": 456,
"type": "computers",
"name": "Mouse",
"price": 15,
"shipping_address": {"city": "Edmonton","province": "AB"}
}
],
"stores_visited": ["Winnipeg","Toronto","Vancouver"],
"coupons_received": [5,10,20],
"children_ages": [1654099180,1654099181,1654099182],
"lottery_tickets":
[
[1,3,5,7,9],
[1,2,3,5,8]
]
}
Hello, my application is divided into Components and Pages folders. Components folder contains files that are reusable. In this case, I use it to create Filter, Search, RowCount, etc from your example. One thing that I haven't been able to do is to use scope in SearchComponent where I define the scope from Pages.
For example, this is what I was trying to do:
SearchComponent:
<script>
export let handler;
export let scope;
let value = '';
</script>
<input type="search" class="form-control search-input" bind:value on:input={() => handler.search(value, {scope})} placeholder="Search..." aria-label="Search">
ProductsPage:
<TableSearch {handler} scope="['system', 'brands']" />
But it doesn't work. Another thing that I've tried was:
SearchComponent:
<script>
export let handler;
export let scope;
let value = '';
</script>
<input type="search" class="form-control search-input" bind:value on:input={() => handler.search(value, [{scope}])} placeholder="Search..." aria-label="Search">
ProductsPage:
<TableSearch {handler} scope="'system', 'brands'" />
But it doesn't work either.
If I hard coded it into SearchComponent, then it will work. But the thing is, I wanted to make the scope dynamic so it can work for different kind of Pages. How do I do that? Thank you.
I'm getting errors when i try to re-set all Rows (reload json-Data) in Row.js
orderBy is null somehow and that fails. The data i'm fetching is exactly the same.
i fixed that temporarily by catching this case in this way:
parse(orderBy) {
// ---- INSERT
if(orderBy === null) {
return {
fn: () => {},
identifier: 'null',
}
}
// ----
if (typeof (orderBy) === 'string') {
return {
fn: (row) => row[orderBy],
identifier: orderBy.toString()
};
}
return {
fn: orderBy,
identifier: orderBy.toString()
};
}
I have a json array with around 200 json items inside the array. Each of these json object has another lvl1 json objects defined, but it is empty ({}) if there is a not an additional lvl2 json object underneath.
I want to filter on the nested lvl2 element, and I needed to write an each block to filter out the "undefined" objects.
The global filter works fine, but when I use the column filter (rowsPerPage is set to 50), I get an undefined message.
When I browser through all possible pages first, the filtering works
Code Example
<tr>
<ThFilter {handler} filterBy={'lvl2'}/>
</tr>
</thead>
<tbody>
{#each $rows as row}
<tr>
{#if row.lvl1.lvl2?.value === undefined}
<td>{row.lvl2 = ""}</td>
{:else }
<td>{row.lvl2 = row.lvl1.lvl2.value}</td>
{/if}
</tr>
{/each}
Is there a better way to accomplish my goal to filter on nested json objects without getting an undefined error message?
Hello. I've spent several days trying to extend the example 'Reactivity example with a simple CRUD' with checkboxes.
Basically, add to each row the typical checkbox:
<td>
<input
class="form-check-input"
type="checkbox"
value={row.id}
id={row.id} />
</td>
The problem is that when changing the page, (and then return to that page) the checked checkboxes are no longer taken into account.
What would be the way to do it?
I have tried several things without success. For example:
bind:checked={$users[row.id]}
Any help is appreciated.
Bonjour @vincjo ,
I'm not sure if you are familiar with Skeleton. It's a relatively new but very polished UI toolkit built on SvelteKit and Tailwind. There was some discussion about trying to integrate a third-party data table component, and I recommended your excellent project for consideration. There was a lot of feedback about pros and cons, and I thought you mind find it interesting:
skeletonlabs/skeleton#538 (comment)
Not asking for any work, just thought you should know!
After updating to the latest version 1.9.4 (coming from 1.7.2), I am getting an error.
VITE v4.3.9 ready in 677 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h to show help
X [ERROR] Could not resolve "$lib"
node_modules/@vincjo/datatables/Datatable.svelte:39:58:
39 │ import { Search, RowsPerPage, RowCount, Pagination } from '$lib';
╵ ~~~~~~
You can mark the path "$lib" as external to exclude it from the bundle, which will remove this
error.
Possible fixes or workarounds:
triggerChange
to manually change page to the first oneI'm not sure if the title makes sense, but I'd like to be able to sort like the following:
handler.sort({
identifier: 'column_name',
direction: 'desc'
});
This is the same format as getSorted() and would allow me to pass these via the URL to the backend:
http://localhost?sort[identifier]=column_name&sort[direction]=desc
Which could be sent as a prop to the frontend so I can sort the data on page load
I install this npm and i m using in my project Typescript.
Is show me this:
Could not find a declaration file for module '@vincjo/datatables'
If the '@vincjo/datatables' package actually exposes this module, try adding a new declaration (.d.ts) file containing `declare module '@vincjo/datatables';
Currently the library liberally uses any, Function and string types. There is nothing wrong with doing it this way, however the developer experience could be meaningfully improved by implementing generics.
I've made a slice of what the implementation might look like in my fork. My vscode formatted it to 2 space indent, so it might look ugly, sorry for that.
User land code in both examples is the same, only $lib/core has been changed.
With current implementation the data type is any and keys are string. Because of that we get no type checking and autocomplete.
After adding some generics we get both.
Since the DataHandler instance gets passed around anyway, it makes sense to attach the type to it.
export default class DataHandler<T extends { [key: string]: unknown } = any>
With that adapting Th component to use the type is pretty straightforward.
<script lang="ts">
type T = $$Generic<{ [key: string]: unknown }>;
type OrderBy<Row> = keyof Row | ((row: Row) => Row[keyof Row]);
import type { DataHandler } from '$lib/core';
export let handler: DataHandler<T>;
export let orderBy: OrderBy<T>;
export let align: 'left' | 'right' | 'center' = 'left';
const identifier = orderBy ? orderBy.toString() : orderBy;
const sorted = handler.getSorted();
</script>
It shouldn't be that hard to extend the same idea to the rest of the library, and I have plentiful free time right now, so I can implement the changes. But that's still a big change and I wanted to discuss it here first.
@vincjo As the author an maintainer of the library, do you feel like the library would benefit from stricter types (like ones in the example above)?
If you have any questions - feel free to ask. And thank you for the awesome work on the library.
Hello, my database has published_at field that contains either date or null. If it's null, then I displayed it in Svelte Datatables by string "Unpublished". If it's not null then I just displayed the date itself.
Now I want to filter if it's published or not. It's easy for the null value because I just need to pass "Unpublished" for the select option value, but I have no idea how for the date value since every date is different. Right now I have a cheesy workaround, since every date that I displayed contains a comma, I set the select option value for not null to comma and that works, but I don't think this is the best? Does Svelte Datatables have function or solution for this kind of filter?
This is my code right now:
TableFilterSelect :
<script>
export let handler;
export let id;
export let defaultSelectedText;
export let options;
export let filterBy = null;
let value = '';
</script>
<select class="form-select" {id} bind:value on:change={() => handler.filter(value, filterBy)}>
<option value="" disabled="{value === ''}" hidden="{value === ''}">{defaultSelectedText}</option>
{#each options as option}
<option value={option.value}>{option.text}</option>
{/each}
</select>
Page :
<TableFilterSelect {handler} id="published_at" filterBy="published_at" defaultSelectedText="Select Published" options={[{"value": ",", "text": "Yes"}, {"value": "Unpublished", "text": "No"}]} />
Thank you.
First of all: Love the tables!
I've encountered a small bug where updating the data for the table prevents the pagination to properly show what page is active.
I initiate the table with the last known data, that is in a localstorage-based store. link
The data is refreshed via an API-call using TanStack-query, and when this finished, the data in the LocalStorageStore is updated.
After this update, the visual key for the active page in the pagination does not update.
I've provided a video to illustrate the issue.
edit: i've noticed the same behaviour when filtering: The number of pages does not adapt, and the page-indicator does not visually update when changing pages
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.