In my code, I have a table and the user can add a new empty row, to the table. I've put a multiply button next to every row. I want the user to be able to click this button and when a dialog opens and he says multiply, I want a copy of that row with the same information to be added to the table. I don't have a clue on how to perform this task. Here is my code, how can I manage this?
HTML of the copy-dialog component:
<button mat-stroked-button class="amber-fg mr-12" (click)="multiply()">Multiply</button>
TS:
multiply(){
}
TS of the table component:
addNewWorkItem() { //adds a new, empty row
let item: IWorkItem = {};
item.WorkItemStateType = this.workItemStates[0];
item.Product = {};
let tempData = this.dataSource.data.splice(0);
tempData.unshift(item);
this.dataSource = new MatTableDataSource(tempData);
this.EditIndex = 0;
this.products = [];
}
openCopyDialog(prm) {
const dialogRef = this._dialog.open(CopyDialogComponent, {
width: "700px",
data: prm,
});
dialogRef.afterClosed().subscribe((result) => {
//console.log(result);
});
}
Related
I created a table in javascript that uses for loop adding 7 empty rows to the HTML table. But, it seems like these rows (or columns) have default sizes. Tried every possible way to resize them, but no luck. I have div element and inside has two tables for reference. Using also "display: inline- block". Here is my javascript code:
document.addEventListener("DOMContentLoaded", function(){
// Get the current page's URL
const currentUrl = window.location.href;
// Check if the current page's URL is the URL of the exam page
if (currentUrl.includes("exam.html")) {
// Get the table element from the HTML document
const lowBoundAndGradeTable = document.querySelector(".low_boundAndGrade");
// create an empty array to store the exam data
let gradeData = [];
// Check if there is data stored in localStorage
if (localStorage.getItem("gradeData")) {
// Retrieve the data from localStorage and parse it as JSON
gradeData = JSON.parse(localStorage.getItem("gradeData"));
}
// Loop through the examData to insert the rows
gradeData.forEach((data, index) => {
// create a new table row
const row = lowBoundAndGradeTable.insertRow();
// insert the cells into the row
const lowBoundCell = row.insertCell();
lowBoundCell.innerHTML = `<input type="text" name="low bound." value="${data.lowBound}">`;
const gradeCell = row.insertCell();
gradeCell.innerHTML = `<input type="text" name="grade" value="${data.grade}">`;
// add a change event listener to each input field
lowBoundCell.querySelector("input").addEventListener("change", function(){
gradeData[index].lowBound = this.value;
localStorage.setItem("gradeData", JSON.stringify(gradeData));
})
gradeCell.querySelector("input").addEventListener("change", function(){
gradeData[index].grade = this.value;
localStorage.setItem("gradeData", JSON.stringify(gradeData));
});
});
// Loop to insert 7 rows if studentData array is empty
if(gradeData.length == 0){
for (let i = 0; i < 7; i++) {
// create a new table row
const row = lowBoundAndGradeTable.insertRow();
// insert the cells into the row
const lowBoundCell = row.insertCell();
lowBoundCell.innerHTML = `<input type="text" name="low bound${i}">`;
const gradeCell = row.insertCell();
gradeCell.innerHTML = `<input type="text" name="grade${i}">`;
// add the data to the examData array
gradeData.push({ lowBound: "", grade: "" });
}
// set the examData in localStorage
localStorage.setItem("gradeData", JSON.stringify(gradeData));
}
}
});
I want to resize the rows so that I can enter numbers in it. But, these cells are kinda big that does not look like user friendly.
I'm currently trying to add column-level filtering to an HTML table, generated from a click event listener, using the TableFilter JavaScript library, however I'm receiving the following error in the console:
Error: Could not instantiate TableFilter: HTML table requires at least 1 row.
The code I'm using to generate the table is below; in essence I'm taking in an array of objects, then looping through them to create a header row, then data rows and then appending the table to a <div>. The table itself renders without issue, but I'm unable to attach filters - could anyone shed any light on why this error is occurring? I'd suspected it might be something to do with trying to add a filter to the table before the element had been rendered, but I couldn't see why that would be the case. I'm aware that the documentation for the library recommends adding a <script> tag under the table, and I've also tried this however I'm not sure how to do that correctly since the table doesn't exist until the click event takes place (hence adding it to the onclick function).
HTML
<html>
<head>
<script src="script.js"></script>
<script src="/TableFilter/dist/tablefilter/tablefilter.js"></script>
</head>
<body>
<button id="my-button">Create Table</button>
<div id="my-table-container">
<!-- table -->
</div>
<script>
button = document.getElementById('my-button');
button.addEventListener('click', renderTable);
</script>
</body>
</html>
JavaScript
const createTableFromObjectArray = (data, containerRef, tableRef) => {
// elements
let container = document.getElementById(containerRef);
let table = document.createElement('table');
table.setAttribute('id', tableRef);
// clear the DOM if the table is already present
while (container.firstChild) {
container.removeChild(container.firstChild);
}
// create header
let headerRow = document.createElement('tr');
const colNames = Object.keys(data[0]);
colNames.forEach(name => {
let headerCell = document.createElement('th');
let headerText = document.createTextNode(name);
headerCell.appendChild(headerText);
headerRow.append(headerCell);
});
table.appendChild(headerRow);
// add rows to table
data.forEach(doc => {
let tableRow = document.createElement('tr');
Object.values(doc).forEach(value => {
let rowCell = document.createElement('td');
let cellText = document.createTextNode(value);
rowCell.appendChild(cellText);
tableRow.appendChild(rowCell);
});
table.appendChild(tableRow);
});
// add table to DOM and add filters
container.appendChild(table);
let tf = new TableFilter(table, {
base_path: '/TableFilter/dist/tablefilter/'
});
tf.init();
}
const renderTable = () => {
const data = [{'Name': 'John', 'Eyes': 'Blue', 'Hair': 'Brown'}];
const containerRef = 'my-table-container';
const tableRef = 'my-table';
createTableFromObjectArray(data, containerRef, tableRef);
}
I have created a CRUD table in which you can delete rows by clicking checkboxes. Now I want to add the following conditions:
If no row is selected, the message "No rows selected" should appear.
If all rows are selected, then the message "Delete all rows?" should appear.
When clicking on single rows the message "Delete this rows?" appears.
How do I implement this?
My Code:
// To delete selected rows
deleteSelectedRows(): void {
const rowsToRemove = this.rows.value.filter((v: any) => v.select).map((v: any) => v.calculatoryBookingsLineValuesId);
const formArray = this.calcBookingsForm.get('rows') as FormArray;
if (rowsToRemove && rowsToRemove !== null) {
const ctrls = [...formArray.controls];
formArray.clear();
let index = 0;
for (const ctrl of ctrls) {
if (!rowsToRemove.includes(ctrl.value.calculatoryBookingsLineValuesId)) {
ctrl.get('calculatoryBookingsLineValuesId').setValue(`${index}`);
formArray.push(ctrl);
index += 1;
}
}
this.rows = formArray;
}
}
// Selected all rows
public toggleCheckboxes() {
this.all = !this.all;
for (const formGroup of this.rows.controls) {
formGroup.get('select').setValue(this.all);
}
}
If rowsToRemove contains actually the rows to delete you can do this:
if(rowsToRemove.length === 0) alert('No rows selected');
else {
let message = rowsToRemove.length === formArray.length ? 'Delete all rows ?' : 'Delete this rows ?';
if (window.confirm(message)) {
// delete rows here
}
}
I'm trying to load and show a CSV in my HTML page using JS. I am able to show the data, but now I want to add the option to add an agree/disagree or check mark/x mark at the end of each row.
So for example, the first row will show some data, and after I looked at it, I will decide if I agree with it or not. After I click agree, the whole row's variable will be set to "true" for example.
So this is my HTML:
<html>
<body>
<input type="file" id="fileSelect" />
<div id="status">Waiting for CSV file.</div>
<table id="csvOutput"></table>
<script src="script.js"></script>
</body>
</html>
This is my script.js:
function buildHeaderElement (header) {
const headerEl = document.createElement('thead')
headerEl.append(buildRowElement(header, true))
return headerEl
}
function buildRowElement (row, header) {
const columns = row.split(',')
const rowEl = document.createElement('tr')
for (column of columns) {
const columnEl = document.createElement(`${header ? 'th' : 'td'}`)
columnEl.textContent = column
rowEl.append(columnEl)
}
return rowEl
}
function populateTable (tableEl, rows) {
const rowEls = [buildHeaderElement(rows.shift())]
for (const row of rows) {
if (!row) { continue }
rowEls.push(buildRowElement(row))
}
tableEl.innerHTML= ''
return tableEl.append(...rowEls)
}
function readSingleFile ({ target: { files } }) {
const file = files[0]
const fileReader = new FileReader()
const status = document.getElementById('status')
if (!file) {
status.textContent = 'No file selected.'
return
}
fileReader.onload = function ({ target: { result: contents } }) {
status.textContent = `File loaded: ${file.name}`
const tableEl = document.getElementById('csvOutput')
const lines = contents.split('\n')
populateTable(tableEl, lines)
status.textContent = `Table built from: ${file.name}`
}
fileReader.readAsText(file)
}
window.addEventListener('DOMContentLoaded', _ => {
document.getElementById('fileSelect').addEventListener('change', readSingleFile)
})
I can't figure out how to add the option I'm looking for at the end of each row, as well as how to mark each row as it's own variable.
To extend your code: after rowEl.append(columnEl), you could call a method to append a hard-coded TD/ TH and also append a checkbox.
As the columns are dynamically created, there is no way of knowing which columns store the unique key(s). Therefore you could store the entire row as a comma separated string as an attribute on the checkbox. Although you'll need to be careful the row data is not too long.
function buildRowElement(rowData, header) {
const columns = rowData.split(',')
const rowEl = document.createElement('tr')
for (column of columns) {
const columnEl = document.createElement(`${header ? 'th' : 'td'}`)
columnEl.textContent = column
rowEl.append(columnEl)
}
rowEl.append(provideColumnAgree(rowData, header))
return rowEl
}
function provideColumnAgree(rowData, header) {
const columnAgree = document.createElement(`${header ? 'th' : 'td'}`)
if (header) {
columnAgree.textContent = 'Agree?';
}
else {
const checkboxAgree = document.createElement(`input`)
checkboxAgree.setAttribute("type", "checkbox");
checkboxAgree.setAttribute("data-row", rowData);
columnAgree.append(checkboxAgree)
}
return columnAgree
}
A working example: https://jsfiddle.net/f74pxkor/
I am setting up a new site in Wix. The page uses an API to fill a simple 4 column table. Sizes, climate, prices, and reserve. I am. trying to figure out how to code a button into column 4 (all rows) that links to the Lightbox "reservation". The reserve button will not be linked to the API, just a form for a customer to fill in.
This is what I currently have. How can I add a button to the last column?
import {getLocationInfo} from 'backend/WssApiService';
import {getLocationReviews} from 'backend/WssApiService';
import {getAvailableLocations} from 'backend/WssApiService';
$w.onReady(function () {
getLocationInfo('xxxxx').then(function(locationInfo) {
//console.log(locationInfo);
$w("#table1").rows = [];
let rows = $w("#table1").rows;
locationInfo.Location.Units.sort((a, b) => (a.Monthly > b.Monthly) ? 1 : -1);
for (var i = 0; i < locationInfo.Location.Units.length; i++) {
var climateControlled = locationInfo.Location.Units[i].SizeDescriptionsField.filter(function(item) {
return item.includes("Climate") && !item.includes("No Climate");
});
//console.log(climateControlled);
if(climateControlled.length > 0)
{
rows.push({Size: locationInfo.Location.Units[i].UnitSize, climate_control : "Yes", Price: '$' + locationInfo.Location.Units[i].Monthly});
}
else
{
rows.push({Size: locationInfo.Location.Units[i].UnitSize, climate_control : "No", Price: '$' + locationInfo.Location.Units[i].Monthly});
}
}
$w("#table1").rows = rows;
You cannot insert a button into a Table in Wix. Use a Repeater for that or add an onCellSelect event handler (https://www.wix.com/corvid/reference/$w.Table.html#onCellSelect) to the table and define the location using code.