Flex Grid - ala titles - with md-card - css

I trying to create a responsive list of cards that would have a minimum width, fill all available space (1, 2, 3 pieces in line according to browser size).
So far I have code what does that:
<div class='md-padding' layout="row" layout-wrap>
<md-card style="min-width: 460px;" ng-repeat="teacher in tc.teachers" flex>
<md-card-title>
<md-card-title-text>
<span class="md-headline" style="padding-bottom: 10px;">{{ teacher.name }}</span>
... other elements ....
</md-card-title-text>
<md-card-title-media>
<div class="md-media-lg card-media" style="height: 228px;">
<img ng-if="teacher.image" ng-src="{{ tc.getImage( teacher ) }}" class="md-card-image" >
</div>
</md-card-title-media>
</md-card-title>
</md-card>
</div>
What does trick is in line #2 style="min-width: 460px;" and flex
However, problem what I facing is that last element is also 'flexed' to the whole width what looks ugly when for example there are 3 cards in a row and the last row has only 1 element...
How I can adjust this last element to be 1/3 in this case and also be responsive to further size changes?
I am using Angular 1.6.1 with angular-material.

To achieve this, you can use Angular Material md-grid-list and md-grid-tile (you can check the doc here and here), you can specify how many columns you want for each screen size (xs, sm, md, lg, etc.) the height of columns and a few other things.
And if there is a last row with, by example, only one element, this element will not be larger than the others.
You can use it like this :
<md-grid-list md-cols-xs="1" md-cols-sm="2" md-cols-md="3" md-cols-lg="4" md-row-height="100px">
<md-grid-tile ng-repeat="teacher in tc.teachers">
<!-- width : 100% -> to make the cards gets the full width -->
<md-card style="width:100%;">
<md-card-title>
<md-card-title-text>
<span class="md-headline">{{ teacher.name }}</span>
... other elements ....
</md-card-title-text>
</md-card-title>
</md-card>
</md-grid-tile>
</md-grid-list>
Here is a working example.

Related

How to change fxFlex size on Window Size change?

I have two divs within my main fxLayout Container. They look like this:
Where the red box is the fxLayout Container, the blue box is the Information and the black box is the Chart. As may be noted, the charts div is larger than the information box's div. I would like it to stay this way when resized at all times. In order to achieve this, I have done the following:
information.component.html:
This component is simply a box with several mat-card. It is within a fxLayout container as well.
<div id = "dataInformation" fxLayout="column" fxLayoutAlign="space-evenly center" fxLayoutGap="5%">
<h1>CrowBox Information</h1>
<!-- ...CODE FOR DROPDOWN BUTTON... -->
<!-- ...EXAMPLE MAT-CARD... -->
<mat-card>
<mat-card-title>NICKNAME</mat-card-title>
<mat-card-content>{{ crowboxNickname }}</mat-card-content>
</mat-card>
<!-- ...SAME MAT-CARDS JUST WITH DIFFERENT PROPERTIES... -->
</div>
The only styling applied is width:75% for .mat-card and font related styling.
I then call this component in another component.
data.component.html
In here, I create the charts, call the information.component and place all of this within another fxLayout container. I also specify what should happen if the window is resized. I would like for the size proportions to remain the same when the container goes from a row to a column. However, for some reason, fxFlex.xs does not seem to be working for me and the chart ends up looking really small as can be seen here:
<div class="wrapper" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="space-evenly center" >
<div id = "charts" fxFlex="60" fxFlex.xs="60">
<!-- THE CHART -->
<div *ngIf="showCoinsDeposited === false" >
<canvas baseChart
[datasets]="crowOnPerchChartData"
[labels]="crowOnPerchChartLabels"
[options]="crowOnPerchChartOptions"
[legend]="crowOnPerchChartLegend"
[chartType]="crowOnPerchChartType"
[colors]="crowOnPerchChartColor"
>
</canvas>
</div>
<!-- ...ANOTHER CHART HERE... -->
</div>
<!-- THE INFORMATION BOX -->
<div fxFlex="27" fxFlex.xs="27" style="border: blue; border-style: double;">
<app-information [crowsOnPerch]="crownsOnPerchValues" [coinsDeposited]="coinsDepositedValues"></app-information>
</div>
</div>
I have set fxFlex.xs for the chart to be 60 and fxFlex.xs for the information box to be 27. I do not think this is being accurately reflected and cannot seem to figure out why. I would like the chart to fill the width of the screen and be much larger. How might I achieve this?
Note: The charts and wrapper do not have any positional styling (only fonts and borders).
If I'm not mistaken, you want the two boxes on different rows while using the xs screens.
Note: fxFlex="60" is a shorthand for fxFlex="1 1 60%".
I think it's better to remove the fxLayout.xs="column" and use fxLayout="row wrap" and add fxFlex.xs="100" or whatever for your chart div. Then after adding fxFlex.xs for the next box, if the sum of the sizes is more than 100, the next item would go to the next row.
<div fxLayout="row wrap" fxLayoutAlign="space-evenly center">
<div fxFlex="60" fxFlex.xs="87" style="background: green">
box1
</div>
<div fxFlex="27" fxFlex.xs="40" style="background: yellow;">
box2
</div>
</div>
Also, there are lots of useful information and examples about flex-layout in here and here.

How to stop flex to auto adjusting, currently based on text length its auto adjusting. I want the entire table to be same size despite any text length

How to get this aligned as i was not able to align
<div class="d-flex justify-content-between">
<span>Total Items: #Model.Count </span>
<div class="d-flex flex-row align-items-center">
<span class="text-black-50">Sort by:</span>
<div class="price ml-2">
<span class="mr-1">price</span>
<i class="fa fa-angle-down"></i>
</div>
</div>
</div>
If you want a quick solution, assign the elements a specific percent width and set flex-grow: 0;.
However, flexbox is probably not the right solution to your problem in the first place, since you can only align items in one direction.
If you need your columns to be aligned, try CSS Grid Layout, which is similar to flexbox but allows you to use both rows AND columns to align your items.
(I know some people have an opposition to W3schools, but their CSS Grid tutorial is helpful for getting started)

Use ngFor items to display another item before the first element

I would like to display an array using ngFor but before the first element I want to display a card (the user can click inside to show a modal)
Here the code :
<div fxFlex="25" *ngFor="let product of products; let i = index">
<div *ngIf="i == 0">
<mat-card (click)="addProduct()" class="mat-card-add-button">
<div fxLayout="row" fxLayoutAlign="center center" fxFlex="100%">
<span style="font-size:32px;text-align:center">+<br />Add product</span>
</div>
</mat-card>
</div>
<div fxLayoutAlign="center stretch">
<mat-card class="product">
<img mat-card-image src="{{product.picture.url}}" alt="photo">
<mat-card-title>{{product.name}}</mat-card-title>
<mat-card-content>
<p>
{{product.description}}
</p>
</mat-card-content>
<mat-card-actions align="end">
</mat-card-actions>
</mat-card>
</div>
</div>
This code doesn't work. It shows the first element (my card) and the second element like this :
Any idea ? Thank you very much !
EDIT :
ngFor loop products :
first loop => my card "add product"
second loop => product A
EDIT 2 : You'll find the answer to this here : Align mat-cards content (image, text and buttons)
In order to get the layout you described I had to adjust your code a little bit. Please refer to this stackblitz for a working example. I've tried to use as much #angular/flex-layout and as little CSS as possible.
EDIT: adjusted the stackblitz according to the comment / follow-up question. The changes are explained within my answer to the follow-up question.
Explanation
First of all you don't need to place your button inside the loop of the products. Therefore you can change the structure to this:
<div class="container">
<mat-card>
<!-- your button content -->
</mat-card>
<mat-card>
<!-- the loop -->
</mat-card>
</div>
Then you need to apply the proper flex-layout attributes.
Since the button is outside the loop now, you need to define the layout attributes on the container:
<div class="container" fxLayout="row wrap" fxLayoutAlign="center center" fxLayoutGap="25px"> ... </div>
In order to style the mat-card containing the button the same way as the mat-cards containing the products your button and your product loop need to have the same width which can be defined by using the fxFlex attribute, e.g.:
<mat-card fxFlex="180px" ... class="product"> <!-- button content --> </mat-card>
<mat-card fxFlex="180px" ... class="product"> <!-- loop content --> </mat-card>
For all styling which can't be defined by the flex-layout a class called "product" will be used.
To make the mat-card containing the button as high as the products some CSS can be used:
.product{
min-height: 250px;
margin-bottom: 25px; /* same as fxLayoutGap for even distribution */
/* additional styling */
}
Keep in mind that if you use the min-height solution your button might be smaller as the products if the height of the product cards exceed 250px.
To always have the button be as high as the products you could use fxLayoutAlign="center stretch" instead of fxLayoutAlign="center center" but all mat-cards will shrink and grow in height depending on the window width. This might not be what you want.

Angular Material List design

I need to design a parent container, which has fixed length child list items (150 px).
1) when the parent container is resized the children list Items should flow from left to right and should break into New Row & the space between the child list items should be evenly distributed.
pls tell me how to achieve this using angular material. pls see the below picture for my requirement.
I tried to implement this.. using the following code.
<div layout-padding layout-fill layout="row" layout-wrap layout-align="space-around start">
<div ng-repeat="student in students"
style="width: 150px; height: 52px;line-height: 52px;min-height: 52px;max-height: 52px;
margin:8px;padding: 0px; border: solid 1px"
draggable="true">
{{student.name}}
</div>
</div>
but this is what I've got
Thanks to Mr. #MikeHarrison... I've edited my code like below & the result is exactly what I've wanted.!
<div class="md-padding" layout="row" layout-fill layout-wrap layout-align="start start">
<md-list-item ng-repeat="student in students" draggable="true" flex-xs="100" flex-sm="50" flex-md="33"
flex-gt-md="25" class="md-3-line" ng-click="alert('hi')">
<img src="../../_resources/images/boy_real.jpg" class="md-avatar"/>
<div class="md-list-item-text">
<h3> {{student.name}} </h3>
<h4> {{student.roll}} </h4>
<p> {{student.desc + ' guy'}} </p>
</div>
<md-divider md-inset></md-divider>
</md-list-item>
</div>
and the result in a browser is
and the result in a mobile is
That will be a totally new control, you will need to create your own using "pieces" of angular material. For example, you can create the list items out of the angular material md-button, host all the buttons inside a md-content if you want scrolling and use the md-layout to align your items. Obviously the most important part will be the styles for your control to have the look and feel of angular material.
The point here is that you will need to create your custom control. I recommend creating your own control module and add the necessary directives, services for you control to work.

Angular Material -md-grid-list content

I am trying to use md-grid-tile of angular material.The Issue I am facing is content of md-grid-tile is aligned center.How to make to work it from Start
<md-content layout-padding>
<md-grid-list md-cols="6"
md-row-height-gt-md="1:1" md-row-height="4:3" md-gutter-gt-md="16px"
md-gutter-gt-sm="8px" md-gutter="4px">
<md-grid-tile
ng-repeat="room in floorDetails.roomDetails"
ng-style="{'background': '#f2f2f2'}"
md-colspan-gt-sm="3"
md-rowspan-gt-sm="2">
<div layout="row" layout-align="center center">
<b >Room1</b>
</div>
<div class='md-padding' layout="row" layout-wrap>
<md-card class="md-card" ng-repeat="bed in room.bedIds">
<md-card-content>
</md-card-content>
</md-card>
</div>
</div>
</md-grid-tile>
</md-grid-list>
Current snap
Desired snap
Try to provide a codepen/plunkr with an example next time, people are more inclined to help you if they have sample code to play around with.
You should read up on angular-material layout. You are mainly missing a <div layout="column" layout-fill> container inside of your md-grid-tile. The layout-fill makes the container fill the whole tile.
You can then adjust the size of your cards with fixed css sizes or flex them. The example flexes them horizontally which may not be desired.
codepen

Resources