update library

This commit is contained in:
JOSEPH LE 2024-02-22 14:07:40 +07:00
parent 51f9867614
commit 3292226eac
3 changed files with 131 additions and 59 deletions

View File

@ -17,6 +17,7 @@ class TableData {
enable: false,
listColumn: [],
},
positionCaption: "top"
};
constructor(tableId, config) {
@ -35,19 +36,20 @@ class TableData {
) {
this.config.order = null;
this.updateConfig(this.config);
// this.attachSortEventListeners(".ri-expand-up-down-fill");
} else {
if (this.config.order === null) {
this.config.order = {
[`order_by_${column}`]: "desc",
};
this.updateConfig(this.config);
this.attachSortEventListeners(".ri-arrow-down-s-fill");
// this.attachSortEventListeners(".ri-arrow-down-s-fill");
} else {
this.config.order = {
[`order_by_${column}`]: "asc",
};
this.updateConfig(this.config);
this.attachSortEventListeners(".ri-arrow-up-s-fill");
// this.attachSortEventListeners(".ri-arrow-up-s-fill");
}
}
}
@ -188,20 +190,20 @@ class TableData {
});
html += "</tbody>";
// Initial pagination use 'data.links'
let htmlPagination = `<ul class="pagination">`;
let htmlPagination = `<ul class="pagination m-0">`;
data.links.map((link) => {
htmlPagination += `
<li class="page-item ${link.active ? "active" : ""}">
<span class="page_number page-link" data-column-name="${
<li class="page-item ${link.active ? "active" : ""}" style="width: 30px; height: 30px;">
<span class="page_number page-link d-flex align-items-center justify-content-center" data-column-name="${
link.url !== null ? link.url.split("=")[1] : null
}" style="cursor: pointer;">${link.label
}" style="cursor: pointer; width: 30px; height: 30px;">${link.label
.replace(" Previous", "")
.replace("Next ", "")}</span>
</li>
`;
});
htmlPagination += "</ul>";
html += `<caption>
html += `<caption style="caption-side: ${this.config.positionCaption}">
<div class="d-flex align-items-center" style="justify-content: space-between;">`;
html += `<div id="perpage">
<!-- Per page -->
@ -251,11 +253,21 @@ class TableData {
per_page: this.config.per_page,
page: this.config.page,
};
let className = "";
// Clear html
$(this.tableId).html("");
// Initial headers
$(this.tableId).append(this.renderHeads());
this.attachSortEventListeners(".ri-expand-up-down-fill");
if (this.config.order === null) {
className = ".ri-expand-up-down-fill";
} else {
if (Object.values(this.config.order)[0] === "asc") {
className = ".ri-arrow-up-s-fill";
} else {
className = ".ri-arrow-down-s-fill";
}
}
this.attachSortEventListeners(className);
// Append 'order' and 'filter' into params if exist
if (this.config.hasOwnProperty("ajax")) {
@ -359,11 +371,12 @@ class TableData {
headers: apiUpdateInfo.headers,
success: (response) => {
// alert("Edit success");
this.notification(`Row update successful`, "success");
this.render();
},
error: function (error) {
console.log(error);
alert("Edit Fail");
this.notification(error, "danger");
},
});
} else {
@ -380,4 +393,33 @@ class TableData {
this.config.per_page = $(`${this.tableId} #perPageSelect`).val();
this.render();
}
// Toast
notification(message, theme) {
var elementToRemove = document.querySelector(".toasts");
if (elementToRemove) {
elementToRemove.remove();
}
var div = document.createElement("div");
div.classList.add("toasts");
div.innerHTML = `
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="liveToast" class="toast text-bg-${theme} border-0" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header border-0">
<strong class="me-auto text-${theme}">Success</strong>
<small>now</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body border-0">
${message}
</div>
</div>
</div>
`;
document.body.appendChild(div);
const toastLiveExample = document.getElementById("liveToast");
const toast = new bootstrap.Toast(toastLiveExample);
toast.show();
}
}

View File

@ -7,11 +7,13 @@ A library used to initialize a basic data table. Includes the main components of
[Tech Stack](#tech-stack)
[Initialization](#initialization)
- [1. Create a table element in HTML](#1-create-a-table-element-in-html)
- [2. Initialize a TableData class in javascript](#2-initialize-a-tabledata-class-in-javascript)
- [3. Render table](#3-render-table)
[Configuration](#configuration)
- [1. Structure of config variable](#1-structure-of-config-variable)
- [2. Default configuration](#2-default-configuration)
- [3. Detailed configuration](#3-detailed-configuration)
@ -21,12 +23,14 @@ A library used to initialize a basic data table. Includes the main components of
[Search](#search)
[Edit cell content directly](#edit-cell-content-directly)
- [1. Functions to use](#1-functions-to-use)
- [2. Example](#2-example)
[Sample data structure](#sample-data-structure)
[Demo](#demo)
## Tech Stack
**Language:** HTML, JavaScript.
@ -93,6 +97,9 @@ var config = {
page: 1,
// Number of lines on the page
per_page: 15,
// Position of caption
// Caption includes per page, detail and pagination
positionCaption: "",
};
```
@ -117,6 +124,7 @@ config = {
enable: false,
listColumn: [],
},
positionCaption: "top",
};
```
@ -124,15 +132,16 @@ _Note: The user-declared configuration will be merged with the default configura
#### 3. Detailed configuration
| Properties | Type | Description |
| ---------- | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data | Array | The array contains data to render when the user wants to pass data directly to the table. By default, the library will receive this `data` variable as rendering data if the user does not declare the config.ajax attribute. |
| order | Object | Columns are sorted by default when initialized. The syntax includes 'order*by*' + column name to sort. Example: `{order_by_id: 'desc'}` |
| filter | Object | Filter based on columns declared in config.heads. Example: `{email: '@gmail.com', name: 'Jonh'}` |
| page | Number | Current page. Default is 1. |
| per_page | Number | Number of lines on the page. Default is 15. |
| heads | Array | An array of objects representing the columns of the table. Each object has two fields: `name` (the column name) and `value` (the display title of the column). It can have a `render` field to customize the display of the header. |
| | | |
| Properties | Type | Description |
| --------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data | Array | The array contains data to render when the user wants to pass data directly to the table. By default, the library will receive this `data` variable as rendering data if the user does not declare the config.ajax attribute. |
| order | Object | Columns are sorted by default when initialized. The syntax includes 'order*by*' + column name to sort. Example: `{order_by_id: 'desc'}` |
| filter | Object | Filter based on columns declared in config.heads. Example: `{email: '@gmail.com', name: 'Jonh'}` |
| page | Number | Current page. Default is 1. |
| per_page | Number | Number of lines on the page. Default is 15. |
| positionCaption | String | Position of caption. Caption includes per page, detail and pagination. Values: `top`, `bottom`. |
| heads | Array | An array of objects representing the columns of the table. Each object has two fields: `name` (the column name) and `value` (the display title of the column). It can have a `render` field to customize the display of the header. |
| | | |
Example:
@ -159,9 +168,9 @@ Example:
];
```
| Properties | Type | Description |
| ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| rowRender | Function | A function used to customize the display of each cell in a row. Takes three parameters: `colName` (the column name), `colValue` (the value of the cell), and `row` (the data of the row). Returns an HTML string to display. |
| Properties | Type | Description |
| ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| rowRender | Function | A function used to customize the display of each cell in a row. Takes three parameters: `colName` (the column name), `colValue` (the value of the cell), and `row` (the data of the row). Returns an HTML string to display. |
Example:
@ -278,11 +287,8 @@ HTML
<label for="code">Code:</label>
<input type="text" class="form-control" id="code" name="code" />
</div>
<button
type="button"
class="btn btn-primary mt-2"
onclick="getFormValues()"
>
<button type="button" class="btn btn-primary mt-2" onclick="getFormValues('filter')">Filter</button>
<button type="button" class="btn btn-warning mt-2" onclick="getFormValues('clear')">Clear</button>
Filter
</button>
</form>
@ -295,21 +301,28 @@ JS
```js
// Get values from form html and append to config -> re-render with new data
const getFormValues = () => {
const formData = {};
const form = document.getElementById("filterForm");
const getFormValues = (action) => {
if (action === "filter") {
const formData = {};
const form = document.getElementById("filterForm");
for (let i = 0; i < form.elements.length; i++) {
const element = form.elements[i];
for (let i = 0; i < form.elements.length; i++) {
const element = form.elements[i];
if (!element.name || element.tagName === "BUTTON") {
continue;
if (!element.name || element.tagName === "BUTTON") {
continue;
}
formData[element.name] = element.value;
}
formData[element.name] = element.value;
config.filter = formData;
}
config.filter = formData;
if (action === "clear") {
config.filter = {};
}
config.page = 1;
tableData.updateConfig(config);
};
```
@ -347,14 +360,15 @@ $("#search_input").on("keyup", function () {
### 1. Functions to use:
| Function | Description | Parameters |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ |
| tableData.cellEdit | Used to initialize a cell that can be edited directly. Used in `config.rowRender` | tableData.cellEdit(colName, colValue). `colName` (the column name), `colValue` (the value of the cell) |
| tableData.actionEdit | Used to initialize an edit button action to perform editing operations. Used in `config.rowRender` and usually declared in the `__actions` column. | tableData.actionEdit(row). `row` (the data of the row) |
| Function | Description | Parameters |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| tableData.cellEdit | Used to initialize a cell that can be edited directly. Used in `config.rowRender` | tableData.cellEdit(colName, colValue). `colName` (the column name), `colValue` (the value of the cell) |
| tableData.actionEdit | Used to initialize an edit button action to perform editing operations. Used in `config.rowRender` and usually declared in the `__actions` column. | tableData.actionEdit(row). `row` (the data of the row) |
### 2. Example
* `rowRender` in `config` variable
- `rowRender` in `config` variable
```js
rowRender: (colName, colValue, row) => {
switch (colName) {
@ -369,7 +383,8 @@ rowRender: (colName, colValue, row) => {
}
};
```
* Result
- Result
![OpenAI Logo](https://i.ibb.co/S36CYxj/Screenshot-2024-02-21-150628.png)
@ -663,14 +678,16 @@ rowRender: (colName, colValue, row) => {
}
```
### *Note: The API that retrieves the data must ensure that the data returned is in the correct structure. Additionally, the sorting and filtering functions have been reconfigured. Information on handling APIs will be updated soon!.*
### _Note: The API that retrieves the data must ensure that the data returned is in the correct structure. Additionally, the sorting and filtering functions have been reconfigured. Information on handling APIs will be updated soon!._
## Demo
[Demo JDataTable](https://jsfiddle.net/joseph_le/eLx17fk9/880/)
## License
[MIT](https://choosealicense.com/licenses/mit/)
## Authors
#### Joseph Le
[@JosephLe](https://github.com/luanlt632000)

View File

@ -16,7 +16,9 @@
<div class="container mt-3">
<h2>JDataTable</h2>
<p>A library used to initialize a basic data table. Includes the main components of a data table such as: sorting, per page, pagination, table. Supports additional configuration of search and filtering features.</p>
<p>A library used to initialize a basic data table. Includes the main components of a data table such as:
sorting, per page, pagination, table. Supports additional configuration of search and filtering features.
</p>
<!-- Filter -->
<div class="card mb-3">
@ -31,7 +33,8 @@
<label for="code">Code:</label>
<input type="text" class="form-control" id="code" name="code">
</div>
<button type="button" class="btn btn-primary mt-2" onclick="getFormValues()">Filter</button>
<button type="button" class="btn btn-primary mt-2" onclick="getFormValues('filter')">Filter</button>
<button type="button" class="btn btn-warning mt-2" onclick="getFormValues('clear')">Clear</button>
</form>
</div>
</div>
@ -43,19 +46,17 @@
<input id="search_input" type="text" class="form-control">
</div>
<!-- Search -->
<!-- Table -->
<table class="table table-striped table-bordered table-hover" id="bookTabe">
</table>
<!-- Table -->
<!-- Pagination -->
<div id="pagination"></div>
<!-- Pagination -->
</div>
<script>
const token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3BheW1lbnQubnN3dGVhbS5uZXQvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzA4NTY3NjcwLCJleHAiOjE3MDg2NTQwNzAsIm5iZiI6MTcwODU2NzY3MCwianRpIjoiMmRpT3RybDNxY3JFeHRrQyIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.7MAtakWsatvd06dQsW_VNb0kcyUBXWqIQ8xUh6f7OqA"
var config = {
// Declare configuration for table headers
// 'render' function is used to customize the header
@ -117,7 +118,7 @@
type: "GET",
data: params,
headers: {
Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3BheW1lbnQubnN3dGVhbS5uZXQvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzA4NDgxMDUwLCJleHAiOjE3MDg1Njc0NTAsIm5iZiI6MTcwODQ4MTA1MCwianRpIjoid0k3alN1OWxlZHJxM3IwSiIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.8aWr2DlfNvQZqBiXIFaDRS8_VsARAl1TEynsuYpZcqY", // Include the token in the request header
Authorization: "Bearer " + token, // Include the token in the request header
},
success: function (response) {
resolve(response);
@ -134,7 +135,7 @@
url: "https://payment.nswteam.net/api/v1/admin/discount/update",
type: "POST",
headers: {
Authorization: "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3BheW1lbnQubnN3dGVhbS5uZXQvYXBpL3YxL2FkbWluL2xvZ2luIiwiaWF0IjoxNzA4NDgxMDUwLCJleHAiOjE3MDg1Njc0NTAsIm5iZiI6MTcwODQ4MTA1MCwianRpIjoid0k3alN1OWxlZHJxM3IwSiIsInN1YiI6IjUiLCJwcnYiOiJkMmZmMjkzMzlhOGEzZTgyYzM1ODJhNWE4ZTczOWRmMTc4OWJiMTJmIn0.8aWr2DlfNvQZqBiXIFaDRS8_VsARAl1TEynsuYpZcqY", // Include the token in the request header
Authorization: "Bearer " + token, // Include the token in the request header
},
},
footer: {
@ -145,6 +146,10 @@
enable: true,
listColumn: ["id", "email", "code", "created_at"]
},
order: {
order_by_id: 'desc'
},
positionCaption: "top"
};
// Initial table
@ -152,21 +157,28 @@
tableData.render();
// Get values from form html and append to config -> re-render with new data
const getFormValues = () => {
const formData = {};
const form = document.getElementById("filterForm");
const getFormValues = (action) => {
if (action === 'filter') {
const formData = {};
const form = document.getElementById("filterForm");
for (let i = 0; i < form.elements.length; i++) {
const element = form.elements[i];
for (let i = 0; i < form.elements.length; i++) {
const element = form.elements[i];
if (!element.name || element.tagName === "BUTTON") {
continue;
if (!element.name || element.tagName === "BUTTON") {
continue;
}
formData[element.name] = element.value;
}
formData[element.name] = element.value;
config.filter = formData;
}
config.filter = formData;
if (action === 'clear') {
config.filter = {};
}
config.page = 1;
tableData.updateConfig(config);
};
@ -177,6 +189,7 @@
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
});
});
</script>
</body>