Primeng make scrollable datatable height responsive - css

PrimeNG DataTable provides a [scrollable] property to define vertical and/or horizontal scrolling. This has to be used with a combination of a set scrollHeight and/or scrollWidth.
How can I have a table that will adjust to whatever the height/width of the window along with maintaining the scrollable feature?
Here is the code I've tried:
<div class="ui-g-12">
<p-dataTable class="ui-g-12" [value]="rows" [hidden]="this.apiService.spinnerIsVisible"
[style]="{ height: 'fit-content', 'margin-top': '10px' }"
[resizableColumns]="false" columnResizeMode="fit" emptyMessage="No records found"
[responsive]="false"
[globalFilter]="tableSearch"
[editable]="true"
[scrollable]="true" scrollHeight="100%" scrollWidth="100%">
<p-header>
<button pButton type="button" icon="fa-refresh" (click)="refresh()" style="float:left"></button>
<label for="tableSearch">Global search: </label>
<input id="tableSearch" #tableSearch type="text" placeholder="type here">
</p-header>
<p-column
*ngFor="let col of cols" [header]="col" [field]="col"
[style]="{'width': '250px', 'min-width': '50px', 'word-wrap': 'break-word'}"
[sortable]="true"
[filter]="true" filterPlaceholder="" filterMatchMode="contains"
[editable]="true">
</p-column>
</p-dataTable>
</div>
But it only solves the responsive width problem. On the screenshot you can se the table which is horizontally scrollable:
Since the height attribute of the p-dataTable is relative to parent in case of percentage value, I've tried to make the parent div to fit content by adding style="height: 100%" to the parent div. Here is the updated code:
<div class="ui-g-12" style="height: 100%">
<p-dataTable class="ui-g-12" [value]="rows" [hidden]="this.apiService.spinnerIsVisible"
[style]="{ height: 'fit-content', 'margin-top': '10px' }"
[resizableColumns]="false" columnResizeMode="fit" emptyMessage="No records found"
[responsive]="false"
[globalFilter]="tableSearch"
[editable]="true"
[scrollable]="true" scrollHeight="100%" scrollWidth="100%">
<p-header>
<button pButton type="button" icon="fa-refresh" (click)="refresh()" style="float:left"></button>
<label for="tableSearch">Global search: </label>
<input id="tableSearch" #tableSearch type="text" placeholder="type here">
</p-header>
<p-column
*ngFor="let col of cols" [header]="col" [field]="col"
[style]="{'width': '250px', 'min-width': '50px', 'word-wrap': 'break-word'}"
[sortable]="true"
[filter]="true" filterPlaceholder="" filterMatchMode="contains"
[editable]="true">
</p-column>
</p-dataTable>
</div>
I also applied following changes to my styles.scss file to make it work (found this in some other question on stackoverflow):
html, body {
height: 100%;
}
But it also didn't work for me:
On the screenshot the height seems to be right, but it is not. When I scroll down, firstly, it goes as it should, but then when close to the end of the table, the scroll bar comes out of the view so I can't see it while I'm still able to scroll. So seems like the datatable is little bit higher than it should be.
So how do I solve this? Any help would be appreciated!

I use this at p-table (not sure if will work on p-datatable).
[scrollHeight]="'calc(100vh - 204px)'"

I don't know if this fits exactly your case, but I solved my issue by setting the scrollHeight datatable property to:
scrollHeight="50vh"
vh refers to:
vh Relative to 1% of the height of the viewport
Viewport = the browser window size. If the viewport is 50cm wide, 1vw = 0.5cm.
You can test different values of the vh and see what fits better.
more on:
https://www.w3schools.com/cssref/css_units.asp

You can get inner height and inner width in ts file like
setInnerWidthHeightParameters()
{
this.innerWidth = window.innerWidth;
this.innerHeight = window.innerHeight * 0.70;
}
and use it as
[scrollHeight]="innerHeight +'px'"
to set it dynamically, it worked for me.

for other who search similar problems, i solve them this way:
mark PARENT div in template with (for example) #leftSidebar
in component use view child :
#ViewChild('leftSidebar', { static: true }) leftSidebar: ElementRef;
you can access it and get position and size like this:
let rect: any = this.leftSidebar.nativeElement.getBoundingClientRect();
let x: number = rect.x;
let y: number = rect.y;
let width: number = rect.width;
let height: number = rect.height;
you can do like Arthur described above and set:
[scrollHeight]="height+'px'"

My story:
Since version 9.1.0, the component is automatically rebuilt depending on the size of the window. But in my case, there were no changes to the window size, but there were changes to the dom tree, since additional elements were removed.
My solution:
scrollHeight='flex';
It didn't help me, because I had a specific pagination that was tied to the scroll, in the end I just, when changing the dom, additionally called the resize event.
setTimeout(() => window.dispatchEvent(new Event('resize')));

Prime NG table introduced flex mode for viewport height adjustment
scrollHeight="flex"
It will take the full height of parent element.

ScrollHeight needs to be 100%.

Related

How to make text area to fit dynamic content completely without any overflow?

This is an angular app (but anyone with css knowledge can help), where there is a text area with dynamic content.
So as the content item.text changes the text area should grow or shrink according to the content to fit the content perfectly without any overflow.
<textarea [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold"></textarea>
// dont worry about the placeholder. you can ignore that.
Currently in my case scrollbar appears & it is not shrinking or growing with the dynamic content.
How can I achieve that?
Or if there is a way to convert a regular html <div> to a textarea, you can suggest that too. But prefers a solution for the above one.
I've tried css rules like, max-content fit-content etc... nothing is working out!
Install npm install ngx-autosize
in html add autosize
<textarea autosize [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold"></textarea>
then in appmodule
put in imports: [AutosizeModule ],
Demo
This can't be accomplished with just css, it needs JavaScript that has quite a few corner cases and can be tricky. Such as, pasted input, input populated programatically, auto filled input, handling screen size changes correctly, and on and on, and doing so in a way that is reusable and performs well.
Given all that, I recommend using a lib for this.
I've used angular material's plenty of times with no issues, just add material to your project (can be done via angular CLI with ng add #angular/material) and either import the MatInputModule from #angular/material/input or TextFieldModule from #angular/cdk/text-field (TextFieldModule is quite a bit smaller) to the module where you want to use it, then do:
<textarea cdkTextareaAutoSize cdkAutosizeMinRows="5" [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold"></textarea>
you can exclude the cdkAutosizeMinRows option and then it will default to 1 row, but you can use that option to set however many minimum rows you'd like to display. You can also use the cdkAutosizeMaxRows option to make it stop growing at a certain number of rows if you wish, otherwise it will grow indefinitely with the content.
blitz: https://stackblitz.com/edit/angular-4zlkw1?file=src%2Fapp%2Ftext-field-autosize-textarea-example.html
docs: https://material.angular.io/components/input/overview#auto-resizing-textarea-elements
https://material.angular.io/cdk/text-field/overview
You can't change the height of the textarea without Javascript. But you can use an editable div instead. In plain HTML something like this would serve the same purpose as an textarea and will resize automatically based on the content.
<div class="font-xl font-bold" contentEditable>Hello World</div>
If you use a <div> which you can edit then it can grow or shrink accordingly.
<div contenteditable="true">This is a div. It is editable. Try to change this text.</p>
The below will loop over the item and compare height to scrollHeight incrementing the height by lineHeight. Then resets the rows once the height is greater than the scroll height
(function () {
const el = document.querySelector('textarea');
dynamicallyResize(el);
el.addEventListener('change', function () { dynamicallyResize(el); });
})();
function dynamicallyResize(el) {
el == undefined && (el = this.target);
const lineHeight = 16;
let i = el.getAttribute('rows'),
height = Math.ceil(el.getBoundingClientRect().height);
el.style.overflow = 'visible'; //triger redraw
while(height < el.scrollHeight) {
height += lineHeight;
i++;
el.setAttribute('rows', i);
}
el.style.overflow = 'auto';
}
<textarea [value]="item.text" [placeholder]="item.text ? '' : 'Your Text Here...'" class="font-xl font-bold" rows="2">Starting text that exceeds the 2 row limit initially placed on this particular text area.</textarea>

Whole button is not clickable on some of my pages

I have a site I created: http://www.raggeddaisy.com
On my Wooden Signs pages and Chalkboards pages, the 'Request More Information', only the top little bit of the button is clickable. The code is the same as my Magnetic Board and Wooden Benches pages. Why would this be? Thanks in advance for your help.
<div id="requestInfoButton">
<form action = "ContactUs.cshtml">
<input type="submit" class="button" value="Request More Information">
</form>
</div>
#requestInfoButton {
font : 10pt 'Century Gothic';
padding-top : 2.25pt;
position : absolute;
left : 500.00pt;
top : 400.50pt;
width : 150pt;
height : 16.50pt;
}
That's because your div with id 'optionsWoodenSignLargePrice' is covering it. I wouldn't advice the styling you've used for just the text and especially the absolute positioning.
However, removing the width and height attributes from the div#optionsWoodenSignLargePrice styles does solve your problem.
It looks like you have two divs that are absolutely positioned with a fixed width that cover the majority of that request more info button. If you remove the width on div#optionsWoodenSignSmallPrice and div#optionsWoodenSignLargePrice your button will be clickable.

CSS "breakpoints" on height of containers

Is there an elegant way to set breakpoints, of sorts, on height of containers.
Example:
Say you have a div and a min-height is set at say 100px. As soon as the content gets too much it doesn't just grow, but grows by another 100px and when the content eventually gets to the bottom of the 200px extend the height by another 100px.
Has anyone do anything like this before?
I don't think this is possible only using CSS, but you can use javascript:
html:
<div id='div'>hello</div>
javascript:
var div = document.getElementById('div');
var height = 0;
div.style.height = height + "px";
while(div.scrollHeight > div.clientHeight){
height += 50;
div.style.height = height+"px";
}
http://jsfiddle.net/fa7d0/JkT7R/
I found your question very interesting so i took the grow bit literally and created a fiddle where content changes is handled and the containing div is increased either in width or height by a defined threshold.
Fiddle: http://jsfiddle.net/Tvswj/1/
The main idea is that you'll only have to listen for DOM changes and then run a jQuery function as such:
// Trigger the resize function on content change
$(myDiv).bind('DOMNodeInserted DOMSubtreeModified DOMNodeRemoved', function () {
$(this).breakpointResize(threshold);
});
If you find it useful, please go ahead and use it and modify as you want.
Credits for DOM events: How to alert ,when div content changes using jquery
You can use container style height: auto ! Important; and min-height: 100px; width: 100%;

How to make a div change its height automatically when the height of its content changes?

I am creating a division, in which there are some elements. For the example below, there is a sentence inside a division. However when the sentence becomes very long when I insert something through ajax, it seems like the height of the division does not change.
<div style="width:300px;min-height:10px;background:red">
<div style="width:100px;height:inherit;background:blue;float:left"></div>
<a style="width:100px;height:10px;float:left">The length of this sentence is always changing.</a>
</div>
you have to set the height for the div using javascript or using jquery
assign a ID to div e.g
<div style="width:300px;min-height:10px;background:red" id="test">
<a>The length of this sentence is always changing.</a>
</div>
$.ajax({
$(function() {
$("#test").width(100).height(200);//set height or width here
});
});
try to set the height here...

when the ajax loader is loaded the text and button below it moves upwards

In my page I use ajax loader gif. When the button is clicked the ajax loader is shown, however the text below it moves to upwards and I want them to be constant I mean not to move.
Is there a way to do this? Thanks for help.
It can be seen from here as well:
http://www.dilyurdu.com
function AjaxLoader()
{
document.getElementById("translation").innerHTML="<img src='ajax-loader.gif' />"
$.ajax({
type: "POST",
url: "test1.php",
success: function(response) {
$("#translation").html("hello");
}
});
}
<div class="informationArea">
<h2><span id="infoaream">caballo</span></h2>
<div id="wordDetailArea">
<h2>Translation:</h2><p><span id="translation">dog</span></p>
<h2>Context:</h2><p><span id="context">I have got a dog.</span></p>
</div>
</div>
This is because the height of <p> tag changes according to its content.
The fix is to use a fixed height.
<p style="height: 25px;"><span id="translation">dog</span></p>
Note: As of ajax request the length of your content may not be consistent. So you should choose a highest value for height
What happens is that your #translation span has a height of 18px, however the ajax-loader.gif has a height of 16px causing the jump, spans and p are inline elements and expand and contract depending on the information that's in them
<div id="translation" style="height: 18px;">hello</div>
or
<span id="translation" style="display:block;height: 18px;">hello</span>
should do the trick.

Resources