Angular Dom:- Add missing cells(td) to angular material calendar - javascript

I am trying to add missing cells in angular material calendar.
Below is my html
<mat-calendar
[dateClass]="dateClass()"
[startAt]="month"
[selected]="selectedDate"
(selectedChange)="onSelect($event)">
</mat-calendar>
I used ViewChildern to access its dom
#ViewChildren(MatCalendar, { read: ElementRef }) calendars: QueryList<ElementRef>;
I was able to add empty extra row to the bottom of angular material calendar
this.calendars.forEach(calendarEl => {
const tbody: HTMLElement = calendarEl.nativeElement.querySelector('tbody');
//ToDO:-- identify last row, count number of cells in last row,if its less than 7 add missing cells
//Added extra row to the bottom
const tr = (document.createElement('tr') as HTMLTableRowElement);
tr.className = 'date-class';
for (let i = 0; i < 7; i++) {
tr.appendChild(document.createElement('td'));
}
tbody.appendChild(tr);
});
Here is the image of calendar I have without adding missing cells(td). Needed to add 4 more cells

Can we do something like getting the last row and add append number of <td> to that row so that total count of <td> children become 7.
let lastRow = calendarEl.nativeElement.querySelector('tbody tr:last-child');
let vaccantColCount = 7 - lastRow.querySelectorAll('td').length;
console.log(vaccantColCount);
while(vaccantColCount > 0) {
lastRow.appendChild(document.createElement('td'));
vaccantColCount--;
}

Related

How to hide columns in HTML table if rows under this column is empty?

I have a table with this columns in HTML page. Razor is used for output. The values are generated dynamically from the database.
ID
Name
Week_1
Week_2
...
Week_52
1
Test1
3
1
2
Test2
2
3
3
3
Test3
5
1
And for example I want to hide column Week_52 because column has no values in all rows.
The column (table -> thead -> tr -> th) has no children, so I don't understand how they can be associated with values in (table -> tbody -> tr -> td).
How can I do this in vanilla javascript? Or maybe there is another solution?
Edited. 0 -> empty
I solved the problem. I added id="myAnchor" to the table with attribute data-currentweek. (I get currentweek value from database using Razor)
function hideWeekColumns(){
const myAnchor = document.getElementById("myAnchor");
currentweek = myAnchor.dataset.currentweek-1;
let weeks = document.getElementsByClassName('column week');
let weeks_array = Array.from( weeks );
weeks_array.splice(0, currentweek); // from position 0, remove 1 element
weeks_array.forEach(element => {
element.style.display = 'none';
});
};
hideWeekColumns();
A slightly different take on the last answer with comments, still in jquery though.
hideemptycols()
function hideemptycols() {
var hide = {} //set an object to track the qty of cells within each column that HAVE zero data
//to hide a column including header, all cells within need to be empty
$('table tbody tr').each(function () { // iterate through all rows
$(this).find('td').each(function (i, v) { // with each of the rows cells
if (!hide[i]) { hide[i] = 0 } //check if the object contains the column index, if not add it and give it a zero value
if ($.trim($(v).text()).length == 0) { //check the length of data if zero
$(v).hide()// hide the cell
}
else {
hide[i] += 1//add 1 against the column for every cell found with data
}
})
})
$.each(hide,function (index, EmptyQty) { //loop the object
if (EmptyQty == 0) { //with each column if the qty of cells with dataequals zero then hide the column
$('table tr th:nth-child(' + index + ')').hide()//get the column by index and hide
}
})
}
By Using jquery you can achieve this
The first step includes a jquery file and then
at bottom add
<script>
let hide = {}
for(let i = 1; i <= 52; i++){
hide[i] = true
}
$('table tbody tr').each(function(){
let cn = -1
$(this).find('td').each(function(){
if($.trim($(this).text()) != '0' && hide[cn]){
hide[cn] = false
}
cn++
})
})
console.log(hide)
for (var key of Object.keys(hide)) {
if(hide[key]){
$('table tr td:nth-child('+key+')').hide()
}
}
</script>

eventlistner in table each row only trigger last row

I'm writing a table allow user click table row and show the hidden rows.
I use addEventListener with loop to allow each table row call the hidden rows under the row.
For example:
row A
row B
after clicking row A, hidden rows will show under row A and above row B
row A
hidden row 1
hidden row 2
row B
however, my code will always and only trigger the last row. If there are 15 rows in the table could click and show rows. Only the hidden rows of 15th row will show. No matter I click 1st row or 15th row, the web always show the 15th row.
var id = "";
var count = 1;
var table = document.getElementById("header_table");
for (var i = 0; i < r.length - 1; i++) {
id = 'detail_' + i;
console.log(id);
table.rows[count].addEventListener('click', function () {
console.log("clicking row " + i);
$("." + id).toggle();
});
count = count + 6;
}
Thank you all, I solved my question. I should bind the parameter into the function.
Reference: Function.prototype.bind
I had a similar problem with my program.
I needed to add an event listener to each row of a table, so I made a for-each loop of the rows and added the event listener:
for (var r of table.childNodes[0].childNodes) {
r.addEventListener("click", () => {
// Do Stuff To Row 'R'
for (var c of r.childNodes) { // Access all cells in row 'r'
c.style.backgroundColor = "blue" // Change the background of all cells in row 'r'
}
}
}
The way the program ran made it so when I would click on a table, row r held the value of the last row in the table, making it such that if row r were to be changed in the event listener, it would only be changing the last row.
It took me hours to figure out, but the solution was to change the loop from var r to let r:
for (let r of table.childNodes[0].childNodes) {
r.addEventListener("click", () => {
// Do Stuff To Row 'r'
for (var c of r.childNodes) { // Access all cells in row 'r'
c.style.backgroundColor = "blue" // Change the background of all cells in row 'r'
}
}
}

How to prevent a table data element from overflowing outside my table

I have an html table with 14 columns and 11 rows. Each td element has a specific id associated with it that correlates to the column and row. For example the 3rd column and 2nd row would be <td id="3-2"></td>. I'm querying a database that has information which goes into each td based on what day the user chooses on a datepicker. If that data meets a certain criteria, I set the rowspan attribute on my td element to "2". The problem is when I do that a <td> gets pushed to the outside of the table. Here is my js so you can get an idea of what I'm doing. The most important part of this starts at the for loop
function createAppointments() {
//clear the dom with the clearTags() function so appointments don't overlap
clearTags();
//get all of the appointments that are related to the current day. Create a date variable equal to the datepicker value
let myDate = document.getElementById('myDate');
let day = myDate.value;
console.log(day);
//update the h1 element to display the current date
document.getElementById('date').innerText = day;
//use day in a doquery to query appts where fid 14(appointment date) is equal to the datepicker value
let appts = qdb.DoQueryWithQueryString(apptsDBID,"{'14'.'EX'.'"+ day + "'}","3.6.18.17.11.37.39.41.42.43.44")//6-appt time/18-service/17-patient/11-trainer/37-element id/39-duration number/41-hex code/42 - notes/43 - top/ 44- left
let records = qdb.selectNodes(appts,"*/table/records/record");
//now we have our xml tree of all of our appointment records
//loop through each record. The element id is a field in quickbase(37) which automatically takes the trainer name and appends a "-" and the start time of the appointment, which corresponds with the td ids.
for(var i=0;i<records.length;i++) {
debugger;
let rec = records[i];
let patient = gf(rec,17);
let service = gf(rec,18);
let notes = gf(rec,42);
let textToDisplay = `${patient}-${service}`;
let eid = gf(rec,37);
let rid = gf(rec,3);
let rspan = gf(rec,39);
let t = gf(rec,43); //top px
let l = gf(rec, 44);//left percentage
console.log(`top is ${t} and left is ${l}`);
let p = document.createElement("p");//create a new paragraph element to put in the table data
let q = document.getElementById(eid);
q.appendChild(p);//append the created paragraph element to the td for the onmouseover event
p.innerText = textToDisplay;
p.setAttribute("id",rid);
p.setAttribute("data-toppx",t);
p.setAttribute("data-leftpercent",l);
p.setAttribute("data-notes", notes);
q.style.backgroundColor = gf(rec,41);
q.style.borderRadius = "10px";
q.style.width = "225px";
p.style.fontWeight = "bold";
q.style.paddingLeft = "15px";
p.setAttribute("onmouseover","showNotes(this)");//set the show notes function as an attribute of the paragraph
p.setAttribute("onmouseleave","hideNotes()");//hide the notes div when not hovered
q.setAttribute("rowspan",gf(rec,39));}//set the row span attribute based on the rspan field in quick base
}
function showNotes(obj) {
let contents = obj.dataset.notes;
let topPX = obj.dataset.toppx;
let leftP = obj.dataset.leftpercent;
console.log(obj);
let notes = document.querySelector('#notes');
notes.style.visibility = "visible";
notes.innerHTML = contents;
console.log(topPX);
console.log(leftP);
notes.style.top = topPX;
notes.style.left = leftP;
}
function hideNotes() {
let notes = document.querySelector('#notes');
notes.style.visibility = "hidden";
}
How can I prevent <td>s from being pushed outside my table? FYI the table is built statically not dynamically.
Try adding some css to your table like setting the table-layout to fixed and for td
word-wrap to break-word
Something like this
td { word-wrap: break-word; } table { table-layout: fixed; width: 100%; }

Adding new rows & columns to an existing table + keeping functionality of table

Here is a link to my JS fiddle
jsfiddle.net/elvo6969/51uLoa7b/2
*new working link
what I'm trying to do is add a new row to my table(that has empty cells which I can write in ) calculate the average of the new row and output it to the last cell in that row.(This is challenging because the first 3 rows should be ignored, as it has Student info like name student number etc)
At the moment when creating a new row it just creates a new single empty cell
Can't seem to figure out how to add a column for the whole table aswell
Any help is greatly appreciated, also almost completely new to JS please excuse any stupidness
function appendRow() {
var tbl = document.getElementById('my-table'), // table reference
row = tbl.insertRow(tbl.rows.length), // append table row
i;
// insert table cells to the new row
for (i = 0; i < tbl.rows[0].cells.length; i++) {
createCell(row.insertCell(i), i, 'row');
}
}
function createCell(cell, text, style) {
var div = document.createElement('div'), // create DIV element
txt = document.createTextNode(text); // create text node
div.appendChild(txt); // append text node to the DIV
div.setAttribute('class', style); // set DIV class attribute
div.setAttribute('className', style); // set DIV class attribute for IE
cell.appendChild(div); // append DIV to the table cell
}
function appendColumn() {
var tbl = document.getElementById('my-table'), // table reference
i;
// open loop for each row and append cell
for (i = 0; i < tbl.rows.length; i++) {
createCell(tbl.rows[i].insertCell(tbl.rows[i].cells.length), i, 'col');
}
}

How to set empty data text in a groupable kendo grid?

I am having a groupable kendo grid.
Please help me out with setting some custom text whenever the grid is empty.
If grid is not groupable i could acheive it using databound funtion.
Here's a version I adapted from KendoGridBinderEx as I wanted a function on databound that could handle not only empty but error cases too. I've modified it back to mostly suit what you're struggling with. When my datasource has errors I'll read them out of the event that I pass into the function itself, thus why you see 'e' referenced as a parameter but not used.
function DisplayNoResultsFound(evt) {
var grid = evt.sender.element;
//Only do this if you can properly find the grid
if (grid.data("kendoGrid") == undefined) {
return;
}
// Get the number of Columns in the grid
var dataSource = grid.data("kendoGrid").dataSource;
var colCount = grid.find('.k-grid-header colgroup > col').length;
//Check for an empty datasource
if (dataSource._view.length == 0) {
//Clear the grid
//you may or may not need this depending on how your datasource returns
grid.find('.k-grid-content tbody').empty();
//Add the no result row
grid.find('.k-grid-content tbody')
.append('<tr class="kendo-data-row"><td colspan="' + colCount + '" style="text-align:center" class="k-state-error"><b>No Results Found</b></td></tr>');
}
// Get visible row count
var rowCount = grid.find('.k-grid-content tbody tr').length;
// If the row count is less that the page size add in the number of missing rows
if (rowCount < dataSource._take) {
var addRows = dataSource._take - rowCount;
for (var i = 0; i < addRows; i++) {
grid.find('.k-grid-content tbody').append('<tr class="kendo-data-row"><td> </td></tr>');
}
}
}
EDIT: Here's a JSFiddle example

Categories

Resources