Force overflow of table row into next row - html

I want to create a calendar component which displays the day on the top and the time on the left.
Looking at Google Calendar, they seem to be using absolute to put the events into the calendar, which I want to avoid.
The next best option to me seemed to be using a table. This option worked fine for the structure of the calendar, but now that I want to add events I have a problem:
Each row represents one hour and each row is 60px tall. Now if I add an event that lasts 75 minutes I need that event to overflow from one row to the next. But instead it just increases the height of the row where I added the event.
Is this behaviour enforced or can I circumvent it somehow?
Here is my current table code:
<table className="w-full">
<caption className="sr-only">Calendar</caption>
<tr className="sticky top-0">
<td className="invisible" />
{[...Array(days).keys()].map((day) => {
return (
<th scope="col" className="border-x bg-white">
{getDayName(calculateDay(day), "en-US").slice(0, 3)}
</th>
);
})}
</tr>
{[...Array(24).keys()].map((hour) => {
return (
<tr className="h-[60px] overflow-visible">
<th scope="row" className="w-16 border">
{hour === 0 ? null : `${hour.toString().padStart(2, "0")}:00`}
</th>
{[...Array(days).keys()].map((day) => {
return (
<>
{day === 1 && hour === 3 ? (
<td className="h-[75px] overflow-visible border bg-red-300">
Hello
</td>
) : (
<td className="border" />
)}
</>
);
})}
</tr>
);
})}
</table>

Related

Display different backgrounds for alternating rows of expanding table

I am using primeNg row expansion feature.
Code is here : https://primefaces.org/primeng/showcase/#/table/rowexpansion
I have a requirement to display yellow background for odd rows and grey background for even rows, but the additional inserted row having the child table should not be included during calculation.
Consider the below html example, where user has expanded the first row. I do not want the rows with 'table-row-expand' class to be considered in the even/odd rule. Here I want first row to have yellow color, second row to have grey color and third row to have yellow again. The expanded row should not have any background.
Note that the .table-row-expand row gets added to the DOM only when user expands the corresponding row. Kindly help me with this problem.
.table-row:nth-child(odd) {
background-color: yellow;
}
.table-row:nth-child(even) {
background-color: grey;
}
<table>
<tr class='header-row'>
<th> </th>
</tr>
<tr class='table-row'>
<td> // first row (should be gray)</td>
</tr>
<tr class='table-row-expand'>
<td> // expanded row (should not be colored)
<div>
<p-table> // child table </p-table>
</div>
</td>
</tr>
<tr class='table-row'>
<td> // second row (should be yellow)</td>
</tr>
<tr class='table-row'>
<td> // third row (should be gray)</td>
</tr>
</table>
Save yourself a headache and drop in a wee bit 'o JavaScript. You may need to put this code in a function to be called when new rows are added.
.table-row.odd {
background-color: yellow;
}
.table-row.even {
background-color: grey;
}
<table>
<tr class='header-row'>
<th> </th>
</tr>
<tr class='table-row'>
<td> // first row (should be gray)</td>
</tr>
<tr class='table-row-expand'>
<td> // expanded row (should not be colored)
<div>
<p-table> // child table </p-table>
</div>
</td>
</tr>
<tr class='table-row'>
<td> // second row (should be yellow)</td>
</tr>
<tr class='table-row'>
<td> // third row (should be gray)</td>
</tr>
</table>
<script>
const styledRows = document.querySelectorAll('.table-row');
const isOdd = n => Boolean(n % 2); // returns true if n / 2 has a remainder
styledRows.forEach((row, i) => {
row.classList.add(isOdd(i) ? 'odd' : 'even');
});
</script>

how to make table without contents in html?

i need to display no results in table like this:
But i got only this :
my table code is:
{this.state.listAllJobSeekers.length > 0 ?
<tbody>
{this.state.listAllJobSeekers.map((JobSeeker,indx)=>
<tr key={indx}>
<td></td>
<td></td>
</tr>
)}
</tbody> :
<tbody className="noResult">
<td>No Results Found</td>
</tbody>
}
if data appears it will show, but if there is no data i need to show table with no rows found
You would need to keep state of the loading state of your request.
As long as that request is loading you can use a different Array to be used to display the rows.
Something like this maybe:
{isLoading ?
new Array(10).fill("").map((item, index) => (
<tr key={index}>
<td></td>
<td></td>
</tr>
)):
this.state.listAllJobSeekers.map((item, index) => (
<tr key={index}>
<td></td>
<td></td>
</tr>))}
In order to always have a nice fixed height of the table, you would need to add empty rows to your listAllJobSeekers as long as there are less than 10 in there
The No rows found text can be placed within the table container with position: absolute; and then centered, relative to the table.
The empty table can be simulated with a set of empty data (in your case, 10 rows with empty cell data).

Angular checkbox gets updated even though ngModel doesn't

I'm working on a shift arrangement app. In it I'm trying to create two tables that show which possible shifts each user has selected.
Both tables display the same data, but arrange it differently. Each table cell has a number of check-boxes that display the possible shifts for each person (in table 1) or the possible people for a shift (in table 2). A checkbox from table 1 that displays shift A option for person X will have the same data-bind as its equivalent checkbox in table 2, which displays person X option for shift A.
The purpose of this is to update the equivalent data in both tables simultaneously when the user couples a person with a shift. The problem: when a checkbox in table 1 is checked/unchecked, all of the check-boxes in table 2 gets checked/unchecked, as shown below:
Here is my template:
<div class="table-container" dir="ltr">
<h3>People</h3>
<table>
<thead>
<th>Name</th>
<th>Options</th>
</thead>
<tbody>
<tr *ngFor="let user of userPreferences">
<td>{{user.name}}</td>
<td>
<div *ngFor="let selection of userYesses[user.name]">
<mat-checkbox class="option-checkbox" dir="ltr" [(ngModel)]="selection.isSelected" name="usc">{{selection.option}}</mat-checkbox>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="table-container" dir="ltr">
<h3>Shifts</h3>
<table>
<thead>
<th>Time</th>
<th>Options</th>
</thead>
<tbody>
<tr *ngFor="let shift of totalShifts">
<td dir="ltr">{{shift.time}}</td>
<td>
<div *ngFor="let selection of shiftYesses[shift.time]">
<mat-checkbox class="option-checkbox" [(ngModel)]="selection.isSelected" name="syc">{{selection.name}}</mat-checkbox>
</div>
</td>
</tr>
</tbody>
</table>
</div>
And here is relevant component code:
this.userPreferences.forEach(u => {
this.userYesses[u.name] = [];
u.preferences.shifts.forEach(week => {
week.forEach(day => {
if (!day.shifts) return;
day.shifts.forEach(shift => {
if (!this.shiftYesses[`${day.date} ${shift.time}`]) this.shiftYesses[`${day.date} ${shift.time}`] = [];
if (shift.isSelected) {
let selection = new Selection(`${day.date} ${shift.time}`, u.name);
this.userYesses[u.name].push(selection);
this.shiftYesses[`${day.date} ${shift.time}`].push(selection);
}
});
});
});
});
The code seems alright to me, am I missing anything? Maybe it's a bug in Angular?
Thanks in advance!
In case anyone else experiences this issue -
After a few days of struggling with this, I stumbled upon this issue from Angular's git - https://github.com/angular/angular/issues/9230
I've read the following in kara's answer:
In the case that you don't want to register a form control, you currently have a few options:
1 - Use ngModel outside the context of a form tag. This will never throw.
<input [(ngModel)]="person.food">
After reading this, I switched the <form> tag into a <div> and everything works as expected now.

PagedList MVC to get data from db based on pagesize

i added PagedList in my project, i have a search view, which basically calls a function to get values from database, my Pagedlist is working fine, but i am not sure if this gets whole data from database or only based on pageSize. For example i have total 30 records, and i added pagesize as 10, so view will show 10 records at a time and 3 pages. Now this PagedList get all 30 values, or only get 10 first time, then if user click on page 2 it gets next 10 records.
Because lets say i have thousand records, so i dont want system to load all of them, i just want to load it according to pagesize , and when user click on second page it gets next records, hope my point is clear, below is my code:
View:
#model PagedList.IPagedList<BackendIntegration.Models.VendorAllTransactions>
#using PagedList.Mvc;
#if (Model != null)
{
<hr />
<div class="form-horizontal">
<table class="table">
<tr class="bg-primary">
<th>
#Html.DisplayName("Date")
</th>
<th>
#Html.DisplayName("Type")
</th>
<th>
#Html.DisplayName("Amount")
</th>
<th>
#Html.DisplayName("User Name")
</th>
<th>
#Html.DisplayName("Vendor Name")
</th>
<th>
#Html.DisplayName("POS ID")
</th>
</tr>
#foreach (var trans in Model)
{
<tr>
<td>
#Html.DisplayFor(model => trans.Date)
</td>
<td>
#Html.DisplayFor(model => trans.TypeDesc)
</td>
<td>
#Html.DisplayFor(model => trans.Amount)
</td>
<td>
#Html.DisplayFor(model => trans.UserName)
</td>
<td>
#Html.DisplayFor(model => trans.VendorName)
</td>
<td>
#Html.DisplayFor(model => trans.POS_ID)
</td>
</tr>
}
</table>
<br />
<div id='Paging' style="text-align: center">
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber)
of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("VendorAllTransactions", new { page }))
</div>
</div>
}
Controller:
public ActionResult VendorAllTransactions(VendorAllTransactionView vw, int? page)
{
int pageSize = 10;
int pageIndex = 1;
pageIndex = page.HasValue ? Convert.ToInt32(page) : 1;
IPagedList<VendorAllTransactions> model = null;
try
{
model = sales.VendorAllTransactions(vw).ToPagedList(pageIndex, pageSize);
}
catch (Exception exp)
{
ModelState.AddModelError("", exp.Message);
}
return View(model);
}
sales.VendorAllTransactions(vw) this call a fucntion with query, which will return records. But this clearly returning all the records. Is Pagedlist get only required number of rows(pagesize) or it gets everything.???
Please advise.
Thanks

td width percentage of table and table header not behaving correctly?

I'm trying to create a soccer schedule table that shows the team and duration like such in this plnkr I made: http://plnkr.co/edit/osuQiVZ2cFKFhbEXylA9?p=preview
I'm trying to make it so the td element (which is duration of game in minutes) for each team is the width percentage of the total time (24 hour period) -- At the same time having the td element appear to start at the appropriate interval in relationship to the 24 hour period th.
I think i'm on the right track getting the width% by dividing the duration in minutes by how many minutes in a day (1440). However I do not know how the td% adjusts itself to the parent element? Is it the tr element width or the table width that the td is adjusting itself off of?
As you can see in the plnkr I'm having trouble scaling the th element so I tried adding two span elements inside 2nd th but that didn't work well as you can see.
Could anyone explain how I might be able to think about working with td% in this case inside the table element?
<table class="table table-default">
<thead>
<th></th>
<th>
<span>00:00</span>
<span class="pull-right">24:00</span>
</th>
</thead>
<tbody>
<tr ng-repeat="team in soccerSchedule">
<td width="100px">
{{team.team}}
</td>
<td class="bg-primary" width="{{widthPercent(secondsToMinutes(team.duration))}}%">
{{secondsToMinutes(team.duration)}} Minutes Long | Start Time: {{team.startTime}}
</td>
</tr>
</tbody>
</table>
And then my angular controller
angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal, $log) {
$scope.soccerSchedule = [
{team: 'lightning', duration: 18000, startTime:"12:00"},
{team: 'thunder', duration: 18000, startTime:"12:00"},
{team: 'force', duration: 18000, startTime:"18:00"},
{team: 'tigers', duration: 18000, startTime:"14:00"},
];
$scope.widthPercent = function(durationInMinutes){
return ((durationInMinutes / 1440) * 100);
};
$scope.secondsToMinutes = function(seconds){
return (seconds / 60);
};
};
What your are trying to achieve (different widths) goes against the tabular way of presenting data.
This can be easily achieved by leaving the columns untouched and adding an extra div inside each column which would represent your timespan. And by using the ng-style directive, you dynamically give it the value based on your calculations.
<td>
<div class="bg-primary" ng-style="{width : ( widthPercent(secondsToMinutes(team.duration)) + '%' ) }">
{{secondsToMinutes(team.duration)}} Minutes Long | Start Time: {{team.startTime}}
</div>
</td>
Here's a plunker: http://plnkr.co/edit/6bPGrqpsJ13SOHTYWskP?p=preview
I've also changed your duration values so you can see it working.
The problem is that table columns have the same width. You can't vary the width of a cell within a row. Instead, you can create many tables. In this case, I'm putting a new 1-row table in each row of the parent table, but there are other ways to achieve it as well.
Plunker: http://plnkr.co/edit/Cc1an7P3rRteeW1LAxsC?p=preview
<tr ng-repeat="team in soccerSchedule">
<td>
<table>
<tr>
<td width="{{100 - widthPercent(secondsToMinutes(team.duration))}}%">
{{team.team}}
</td>
<td class="bg-primary" width="{{widthPercent(secondsToMinutes(team.duration))}}%">
{{secondsToMinutes(team.duration)}} Minutes Long | Start Time: {{team.startTime}}
</td>
</tr>
</table>
</td>
</tr>