Nativescript: How to make label no longer than the width of its container in a grid flexbox? - css

I'm writing an app with NativeScript 6.4.1 and Angular 8.
On the home page of my app, I need to have a list of buttons with a label underneath the button.
I want the container that holds the button and the text to be the same width for all. If the text is too long it will go onto the next line rather than expand the size of the parent container.
I have tried to use FlexboxLayout for this purpose but I notice that the parent containers just expand:
https://play.nativescript.org/?template=play-ng&id=jbpqMk&v=5
I guess I need some flexiblity in the layout as well; maybe have the ability to configure if its 2 or 3 columns.
Would I be better off using GridLayout?
Here is a code snippet:
home.html
<FlexboxLayout backgroundColor="pink" flexWrap="wrap" justifyContent="center">
<ns-home-button *ngFor="let n of list" name="{{ n.name }}"></ns-home-button>
</FlexboxLayout>
Desired Result:
Current Result:

Interestingly, the cells you've shown in your demo are properly aligned as per your flow specifications. Using a GridLayout would be possible, but not really ideal. The GridLayout would need all of its rows counted and specified, which is annoying, and it would also force its children to fit within it, rather than expand based on children (like FlexboxLayout or StackLayout).
Instead, just put a width on each item. The easiest two ways to do this are by wrapping each element:
<FlexboxLayout backgroundColor="pink" flexWrap="wrap" justifyContent="center">
<StackLayout width="33%" *ngFor="let n of list">
<ns-home-button name="{{ n.name }}"></ns-home-button>
</StackLayout>
</FlexboxLayout>
or by modifying the component spec:
<FlexboxLayout backgroundColor="pink" flexWrap="wrap" justifyContent="center">
<ns-home-button width="33%" *ngFor="let n of list" name="{{ n.name }}"></ns-home-button>
</FlexboxLayout>
#Input() width: string;
<FlexboxLayout [width]="width" ...>
...
</FlexboxLayout>

Related

What to use when i need a box with a border and some different text with different fonts and sizee

Hi i have spend some days searching for the answer how to solve this
This is what i want, just made a image how it should look like
What is the best solution to use to solve this?
I tryed to do this with a Frame but it just allowed be to use 1 content .
Can i use more then one content in some way
( Content can just have one setup of fontcolor and fontsize and so on. )
I just get to this part
Here i try to put a label with margin with - so it go above.
But this is really bad to to. because i need to have the implementation under the frams. like this.
_stack.Children.Add(frame);
_stack.Children.Add(bordertext);
and when i fill the frame with content the lable apear in another position because how it relate to the margin when the Frame get higher.
But if i put the lable implementation above the Frame then it appear in the background of the frame
_stack.Children.Add(bordertext);
_stack.Children.Add(frame);
And the label get weard with the shadow that i cant figure out how to get rid of.
C#
Frame frame = new Frame
{
BorderColor = Color.Brown,
CornerRadius = 10,
HasShadow = false,
Margin = 10,
BackgroundColor = Color.White,
};
Label bordertext = new Label( );
bordertext.Text = "BorderText";
bordertext.Margin = new Thickness(40, -65,0 , 0);
bordertext.BackgroundColor = Color.White;
_stack.Children.Add(frame);
_stack.Children.Add(bordertext);
PART OF THE SOLUTION
#Jason 's solution to put
the Content in a Stacklayout and then put it in a Frame Solves the problem with having more then one text with different font,sizes and stuff.
But i put a text outside the Stacklayout so i can have the Text on the border. But because i put the Bordertext first and then the Frame. Then the Border text gets in the background.
If i put it after the Frame then i gets in the front. But then i have a big problem with dynamic text that the BorderText will appear very strange depending on how much text.
How i cant put the BorderText in front even if i implement in before so i cant move it down a little bit.
_stack.Children.Add(new Label { Text = "Bordertext", Margin = new Thickness(0, 0, 0, -25) });
_stack.Children.Add(_frame);
To compose a layout, first determine what boxes (rectangles) you need inside other boxes. Each "box" is some container (layout) type.
I see one box "A", the size of the parent-container, containing the border lines "B", overlaid by a box "C" that blocks part of one line, and contains a text "D".
I see a second box "E", inset slightly from the parent-container, which contains additional content "F".
To overlay multiple items, use a one-cell Grid, with children at (row,column) of 0,0 - which can be omitted because is default:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FormsApp1.MainPage">
<Grid BackgroundColor="Violet">
<!-- Border lines formed by one box visually "inside" another, via margins.
Instead use "Rectangle" if need rounded corners. -->
<BoxView BackgroundColor="Red" Margin="10"/>
<BoxView BackgroundColor="LightCoral" Margin="16"/>
<!-- Text "box" given size by putting inside a StackLayout. -->
<!-- Some of these dimensions may not be needed. -->
<StackLayout WidthRequest="300" HeightRequest="30">
<Label Text="Header Text" TextColor="Black" BackgroundColor="White" FontSize="18"
HorizontalOptions="Start"
WidthRequest="150" HeightRequest="30" Margin="20,0" Padding="20,0,0,0"/>
</StackLayout>
<!-- this contains your contents. -->
<StackLayout BackgroundColor="#2196F3" Padding="10" Margin="40">
<Label Text="Content line 1" HorizontalTextAlignment="Center" TextColor="White"/>
<Label Text="Content line 2" HorizontalTextAlignment="Center" TextColor="White"/>
</StackLayout>
</Grid>
</ContentPage>
"Positioning" is done via "Margin" and "Padding" properties.
I've used various colors, so you can see the parts of this layout. "ContentPage" wrapper might not be needed; use whatever your app expects as topmost container.
layout of group' frame' with header text:

Set Nativescript Chart Lines to Max Width

You can see from the image below, the chart lines don't go all the way to the edge of the StackLayout container. I've tried adding negative margins on the StackLayout but they're inconsistent depending on how much data I have in the chart and the margins can fluctuate. And between Android & iOS, the margins are always different.
Nativescript Playground sample:
play.nativescript.org/?template=play-ng&id=I8lOBP
This is the bad version:
In the image, you'll notice on the right and left edges, there's dark strips of the emulator window. I'm looking for a way for the red area line to touch those edges. It's hard to see in the image but the bottom also needs to touch the bottom of the StackLayout container.
<StackLayout>
<RadCartesianChart
height="100%"
width="100%"
class="default-background">
<CategoricalAxis
lineColor="#f5f5f5"
hidden="true"
lineHidden="true"
lineThickness="1"
labelLayoutMode="Inner"
tkCartesianHorizontalAxis>
</CategoricalAxis>
<LinearAxis
lineColor="#f5f5f5"
hidden="true"
lineHidden="true"
lineThickness="1"
labelLayoutMode="Inner"
[maximum]="max"
[minimum]="min"
tkCartesianVerticalAxis>
</LinearAxis>
<AreaSeries
tkCartesianSeries
seriesName="Area"
showLabels="false"
categoryProperty="Date"
[items]="areaSource$ | async"
valueProperty="Amount"
selectionMode="None">
</AreaSeries>
<RadCartesianChartGrid
tkCartesianGrid
horizontalLinesVisible="false"
verticalLinesVisible="false"
verticalStripLinesVisible="false"
horizontalStripLinesVisible="false"
horizontalStrokeColor="#181818">
</RadCartesianChartGrid>
<Palette tkCartesianPalette seriesName="Area">
<PaletteEntry
tkCartesianPaletteEntry
opacity="1"
[fillColor]="fillColor"
[strokeColor]="lineColor"
android:strokeWidth="4"
ios:strokeWidth="2">
</PaletteEntry>
<PaletteEntry
tkCartesianPaletteEntry
[fillColor]="fillColor"
strokeColor="#181818"
strokeWidth="0">
</PaletteEntry>
</Palette>
</RadCartesianChart>
</StackLayout>
Here's what I want it to look like (credit: photoshop).
You should be setting the horizontalZoom property, probably upping its current value by about 30%.
const screen = require("tns-core-modules/platform").screen;
let widthDIPs = screen.mainScreen.widthDIPs;
<StackLayout>
<RadCartesianChart
height="100%"
[width]="widthDIPs"
class="default-background">
<CategoricalAxis
(...)
src: https://docs.nativescript.org/angular/ui/styling#supported-measurement-units

Clarity container element to wrap clr-datagrid element

Is there any Clarity element to wrap the container of clr-datagrid element in html? Please suggest me the solution to wrap the clr-datagrid using clarity element.
In the below instead of "div" element, i want to use clarity element. So that clrDgLoading will work. Here now it is not working as div is not known to clrDgLoading.
<div [clrDgLoading]="loading">
<clr-datagrid *ngIf="some condition which i need">
....................
</clr-datagrid>
</div>
I want loader to work first and then i will add my condition to clr-datagrid whether to show/hide the table or not(depends on the data presence).
I would suggest to use a spinner like the angular material spinner or the ngx-spinner for progress before loading the datagrid.
Example material spinner:
<mat-spinner></mat-spinner>
Example ngx-spinner:
<ngx-spinner
bdOpacity = 0.9bdColor = "#333"size = "medium"color = "#fff"type = "line-spin-clockwise-fade"[fullScreen] = "false"
>
<p style="color: white" > Loading... </p>
DEMO ngx-spinner

How to make Material UI TextField less wide when in Table

I've got a Material UI Table.
I build it like this:
tableValues.map((curRow, row) => {
tableRows.push(
<TableRow key={this.state.key + "_row_" + row}>
{curRow.map((cellContent, col) => {
let adHocProps = {...this.props, type:"Text", label:"", value:cellContent}
return (
<TableCell className={classes.tableCell} key={this.props.key + "_row:" + row + "_col:" + col}>
{col===0 && this.props.rowHeaders ?
<div className={classes.header}>{cellContent}</div> :
<Question {...adHocProps} stateChangeHandler={this.handleTableChange("in build")} />}
</TableCell>
)})}
</TableRow>
);
return null;
});
return (
<Table key={this.props.key + "_table"} className={classes.table}>
<TableHead>
<TableRow>
{this.props.colHeaders.map((header) => <TableCell className={classes.tableCell} key={this.props.id + header}><div className={classes.header}>{header}</div></TableCell>)}
</TableRow>
</TableHead>
<TableBody>
{tableRows}
</TableBody>
</Table>
);
The Question is actually a glorified [TextField]2 created thusly:
<div>
<TextField
value={this.state.value}
onChange={this.handleTextChange(this.props.key)}
key={this.props.key}
id={this.props.id}
label={this.props.label}
placeholder={realPlaceholder}
className={classes.textField}
fullWidth
xmlvalue={this.props.XMLValue}
/>
</div>
... and then wrapped in Paper.
The styles are:
tableCell: {
padding: 5,
},
textField: {
padding: 0,
margin: 0,
backgroundColor: "#191",
}
This works, I get the appropriate content in each cell.... but the Question element is way wider than needed, and appear to have a min width and some padding I can't remove.
The table is full-width until you get to a certain point, then notice here:
that when the window is shrunk below a certain level, the table doesn't shrink any further. Acting as if the elements inside have a minimum width.
As a process of investigation, I change the Question element to simply return "Hi". When it does, the table then looks like this:
(which is to say, it condenses nicely... still too much padding on the tops and bottom and right, but WAY better)
So that leads me to believe the issue is with my Question component. I should note this happens on other Questions as well -- they all appear to have a min width when a width is not defined for them... UNLESS they are placed inside a container that has a designated width such as a Material UI Grid. For example, when placed in a `Grid and the window is shrunk, they shrink appropriately:
So why isn't the Table/TableCell also shrinking the TextField like the Grid does? (or: how do I remove the apparent "MinWidth" on my textFields?) Do Material UI TextFields have a minimum width if one isn't otherwise specified?
For what it's worth, I have tried specifying the column widths of the table -- with success when the table is wide, but it still doesn't solve the apparent minimum width issue.
I have also tried changing the Question component to <input type="text" name="fname" /> and still have the same problem. It's interesting that that the Question component is simply "hi" the problem disappears but that when it's an input, it shows up.
I have discovered that the native input fields default width is 20 characters: https://www.w3schools.com/tags/att_input_size.asp
The 'size' property is key here:
Specifies the width of an element, in characters. Default
value is 20
To set the width of the TextField, you must pass properties to the native input field.
If you wish to alter the properties applied to the native input, you
can do so as follows:
const inputProps = {
step: 300,
};
return <TextField id="time" type="time" inputProps={inputProps} />;
For my use case, the following modified the sizes of the TextFields to be 10 characters in size:
<TextField
value={this.state.value}
onChange={this.handleTextChange(this.props.key)}
key={this.props.key}
id={this.props.id}
label={this.props.label}
placeholder={realPlaceholder}
className={classes.textField}
fullWidth
xmlvalue={this.props.XMLValue}
inputProps={{
size: 10
}}
/>
Unfortunately, this is a bit squishy... it neither holds the input field at exactly size nor does it treat it like a minimum size.... There appears to be some heirarchy of sizing in play between GridItems, table Columns, free-flow flex areas, and the actual TextField elements... and I'm not well versed enough to know what always 'wins'.

Primeng make scrollable datatable height responsive

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%.

Resources