Trying to display a list of things in a single line using flex display. I am using angular 7 for development.
Below is the HTML I implemented:
<div class="d-flex">
<span>Other: </span>
<div class="d-flex">
<div *ngFor="let allergy of allergies; let i = index">
<span *ngIf="i > 0">,</span><span *ngIf="allergy"> {{ allergy }}</span>
<span *ngIf="!allergy">None</span>
</div>
</div>
</div>
d-flex is the bootstrap display class:
.d-flex {
display: -webkit-box!important;
display: -ms-flexbox!important;
display: flex!important;
}
In my component allergies is set to
allergies = ['dermatological allergies', 'dust', 'pollen', 'mold'];
Display:
As seen, the list does not break properly and the display is distorted. This happens when the list length exceeds the computed column width. How can I display it as a list that breaks properly as expected? Please let me know if I can improve my question or if I can provide any more information.
I think this is what you want:
<div class="d-flex">
<span>Other: </span>
<div>
<ng-container *ngFor="let allergy of allergies; let i = index">
<span *ngIf="allergy">{{ allergy }}</span><span *ngIf="i < allergies.length - 1">, </span>
<span *ngIf="!allergy">None</span>
</ng-container>
</div>
</div>
Here is a stackblitz example showing how this looks like.
Hope this helps...
With angular, I suggest you to use Flex-layout from Angular.
With your to wrap your item, use row wrap
With your code, you can also do:
<div class="d-flex">
...
...
<div *ngFor="let allergy of allergies; let i = index" class="d-flex">
...
</div>
</div>
</div>
Related
Within an Angular project, I'm trying to replicate this.
I have a parent mat-card element which will house a mat-grid-list.
The mat-grid-list will then contain multiple (10) mat-cards which would in turn surround another mat-card (see the example image for the layout provided).
Is something like this possible and if so, what would the best approach be to do so?
Currently, with what I have, the child mat-cards (mat-card-2's in the example) are displaying in a single column.
HTML
The following is within a separate component which calls the "x" component
<mat-card-content *ngFor="let x of xs">
<div>
<app-x-synopsis [x]="x" ></app-x-synopsis>
</div>
</mat-card-content>
HTML for the "x" component
<mat-grid-list cols="6">
<mat-grid-tile id="table-grid" [colspan]="6" [rowspan]="1">
<mat-card class="x-synopsis-card">
<mat-card-header class="x-name">
<mat-card-title class="title">
{{ x.name }}
</mat-card-title>
<div style="flex-grow: 1"></div>
<button mat-icon-button>
<fa-icon [icon]="faInfoCircle"></fa-icon>
</button>
</mat-card-header>
<mat-card-content class="x-occupied" *ngIf="hasX()">
<div class="x-container" fxLayout="row wrap" fxLayoutAlign="space-around center">
<div class="ux-container" fxLayout="column">
<div class="ux-value">
{{ x.y.z }}
</div>
<div class="ux-title">
UX
</div>
</div>
<div class="abc">
{{ x.y.a }}
</div>
</div>
</mat-card-content>
<mat-card-content class="x-vacant" *ngIf="!x()">
<div class="x-container" fxLayout="row wrap" fxLayoutAlign="space-around center">
<div class="label">
VACANT
</div>
</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
</mat-grid-list>
Any help would be greatly appreciated, I am also happy to provide anymore information where possible :) Thanks.
I have a quiz application that displays multiple questions along with their respective answers. I am wanting to make it so each question has its own unique set of radio checkboxes so that I can easily bind that to a "Selected" property of an answer. When I try to do this it will let me select one radio button but then the other ones glitch out.
Video of problem. This seems to only happen when I put them inside of a mat-radio-group but I thought I had to use one to get different sets of radio buttons.
<!--start of exam -->
<mat-step [stepControl]="examForm">
<ng-template matStepLabel>
<span *ngIf="worksheetComplete"><span *ngIf="programLocked">Edit </span>Exam</span>
<span *ngIf="!worksheetComplete" class="text-red-400"><span *ngIf="programLocked">Edit </span>Exam (Incomplete)</span>
</ng-template>
<div *ngIf="examAttemptMap.passing" fxLayout="column" fxLayoutGap="24px">
<span *ngIf="sharedService.tablet" class="f-s-18">Exam</span>
<div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="24px">
<span fxFlex="70" class="f-s-20">You have already passed the exam. Please continue through the application.</span>
</div>
</div>
<div *ngIf="!examAttemptMap.passing" fxLayout="column" fxLayoutGap="24px">
<span *ngIf="sharedService.tablet" class="f-s-18">Exam</span>
<div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="24px">
<span fxFlex="70" class="f-s-20">Please answer the following questions. You may attempt this as many times as you would like.
</span>
</div>
<mat-radio-group formControlName="{{question.text}}" *ngFor="let question of examAttemptMap.questions; let elementIndex = index">
<!--Questions-->
<div fxLayout="column" fxFlex="100" >
<!--Core Elements-->
<div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="8px" fxLayoutAlign="start center" fxLayoutAlign.lt-md="" style="padding-bottom: 1%" >
<span><strong>({{elementIndex + 1}})</strong></span>
<span>{{question.text}}</span>
</div>
<!--Answers-->
<div fxLayout="row">
<span fxFlex="5"></span>
<div fxLayout="column" fxFlex="80">
<div fxLayout="column" *ngFor="let answer of question.examAnswers; let subSectionIndex = index" fxLayoutGap="8px">
<div fxLayout="row" fxLayout.lt-md="column" fxLayoutGap="8px" fxLayoutAlign="start center" fxLayoutAlign.lt-md="">
<mat-radio-button value="true"></mat-radio-button>
<mat-card [ngStyle]="{'background-color':(answer.selected == true) ? '#53a66c' : '#00559525' }" (click)="highlightCard(answer, question.examAnswers)" [id]="answer.selected" class="card" >
<span ><strong>({{getIndexLetter(subSectionIndex, false)}})</strong></span>
<span style="padding-left: 1%">{{answer.text}}</span>
</mat-card>
</div>
</div>
</div>
</div>
</div>
</mat-radio-group>
</div>
I created a angular dropdown component "app-ec-dropdown" using https://www.npmjs.com/package/#ng-select/ng-select
<div class="inline required">
*
</div>
<div class="input-container inline">
<ng-select
class="custom"
[items]="items"
bindLabel="Name"
bindValue="Id"
(focus)="focus()"
(close)="close()"
(clear)="clear()"
(blur)="blur()"
placeholder="Select"
[(ngModel)]="selectedId"
[required]="required"
>
</ng-select>
<div *ngIf="!validatationPassed()">
<div class="row alert alert-danger alert-div">
<span>
Required field
</span>
</div>
</div>
</div>
CSS for above component
.input-container {
width: 95%;
}
.inline {
display: inline;
}
.required {
vertical-align: top;
color: red;
width: 2%;
}
Now i am using above component in parent component
<div class="col-sm-4">
<app-ec-dropdown
name="RegionId"
[items]="regions"
(onChange)="onRegionChange($event)"
[selectedId]="state.RegionId"
[required]="regionDropDownValidator.required"
[ecDropDownValidator]="regionDropDownValidator"
[(ngModel)]="regionDropDownValidator.selectedId"
ngDefaultControl
> </app-ec-dropdown>
</div>
for Region Dropdown, I want red asterisk, to be placed as in "State Name" textbox and then dropdown and validation message in the adjacent div.
Screen grab:
After playing around with your code, I thought about the way that I would do it.
I noticed that the actual label isn't included in your example above, so I assume that it's being included within a column to the left of the <div class="col-sm-4"> element where you're consuming the <app-ec-dropdown> component which I assume that you have defined with the first code block.
My advice which will be the easiest and most correct (in my opinion), would be to add the label as an #Input property in your code for the <app-ec-dropdown> component.
Then you can place it closer to the asterisk character.
So add this to your EcDropdownComponent TypeScript:
#Input()
public label: string = '';
Then add the input attribute where you consume your component:
<app-ec-dropdown
name="RegionId"
[items]="regions"
label="State Name"
(onChange)="onRegionChange($event)"
[selectedId]="state.RegionId"
[required]="regionDropDownValidator.required"
[ecDropDownValidator]="regionDropDownValidator"
[(ngModel)]="regionDropDownValidator.selectedId"
ngDefaultControl>
</app-ec-dropdown>
Then you can use the CSS grid to define the layout within your component:
<div class="row">
<!-- Label -->
<div class="col-sm-4">
<div class="label">
{{label}}
<span class="inline required"> * </span>
</div>
</div>
<!-- Select Input -->
<div class="col-md-8">
<div class="input-container inline">
<ng-select
class="custom"
[items]="items"
bindLabel="Name"
bindValue="Id"
(focus)="focus.emit()"
(close)="close.emit()"
(clear)="clear.emit()"
(blur)="blur.emit()"
placeholder="Select"
[(ngModel)]="selectedId"
[required]="required">
</ng-select>
<div *ngIf="!validatationPassed()">
<div class="row alert alert-danger alert-div">
<span>
Required field
</span>
</div>
</div>
</div>
</div>
</div>
The nice thing about this approach is that you have a completely self-contained component which doesn't need to worry about anything outside of it's scope.
If you're concerned about variable widths using Bootstrap and the grid system.
You can also pass the grid column style in as an #Input property to the component so that you're providing more control to the consuming component.
I have a problem with Anguar8 and ngIf:
I have a code that creates div which loads some images and their details to a page from a json with conditon:
HTML Code:
<div class="row" >
<div class="col-md-2 col-6 col-sm-4" style="margin-bottom: 1em;" *ngFor="let item of product; let i=index"> <br>
<div class="box" *ngIf="i>35">
<img [src]="item.photo" alt="image slide" style="display: block; width: 100%;">
<div class="text-center">
<h6>{{item.name}}</h6>
<h6>MRP : ₹ {{item.price}}</h6>
</div>
</div>
</div>
</div>
The problem is, that angular creates an empty div with this comment in it:
<div _ngcontent-oio-c3="" class="col-md-2 col-6 col-sm-4" style="margin-bottom: 1em;"><br _ngcontent-oio-c3=""><!--bindings={
"ng-reflect-ng-if": "false"
}--></div>
You may write *ngFor="let item of product | slice:0:35;".
Reference https://angular.io/api/common/SlicePipe
There are two options:
1.You can filter the list using pipe to avoid
2.You can try this should not create any template
<div *ngIf="i>35; else noData">
{{data}}
</div>
<ng-template #noData>
</ng-template>
Is it possible to expand my cards individually rather than as they are doing now, all together?
I have defined an array of JSON data that will be used to fill the details of the cards, but I just cannot seem to get them to expand individually.
Simple data
export const DATA = [
{
name: 'Some name 1',
},
{
name: 'Some name 2',
}
];
.ts file
export class AppComponent {
data;
expanded = [];
constructor(public toast: MatSnackBar) {
this.data = DATA;
}
}
html
<div class="container">
<mat-card *ngFor="let item of data" #panel [ngClass]="{expanded: expanded[item]}" [class.mat-elevation-z8]="expanded[item]">
<div class="header">
Some content here
<div class="toggle">
<button mat-icon-button>
<mat-icon *ngIf="!expanded[item]" (click)="expanded[panel]=!expanded[item]">
edit
</mat-icon>
<mat-icon *ngIf="expanded[item]" (click)="expanded[item]=!expanded[item]">cancel</mat-icon>
</button>
</div>
</div>
<div class="body" *ngIf="expanded[item]">
Some content here
</div>
</mat-card>
</div>
Here is my stackblitz for you to play with
Edit:
My 'logic' above comes from seeing something similarly implemented like this:
<mat-card #panel *ngFor="let x of [1,2,3]" [ngClass]="{expanded: thisExpands[x]}">
<div class="header">
<div class="toggle">
<button
mat-flat-button
(click)="thisExpands[x]=!thisExpands[x]"
...
However these cards are generated from a much more simple array of data.
you can use index to access the particular item in the forLoop:
<mat-card *ngFor="let item of data; let i = index">
</mat-card>
Your HTML Code:
<div class="container">
<mat-card *ngFor="let item of data; let i = index" #panel [ngClass]="{expanded: expanded[i]}" [class.mat-elevation-z8]="expanded[i]">
<div class="header">
Some content here
<div class="toggle">
<button mat-icon-button>
<mat-icon *ngIf="!expanded[i]" (click)="expanded[i]=!expanded[i]">
edit
</mat-icon>
<mat-icon *ngIf="expanded[i]" (click)="expanded[i]=!expanded[i]">cancel</mat-icon>
</button>
</div>
</div>
<div class="body" *ngIf="expanded[item]">
Some content here
</div>
</mat-card>
</div>
StackBlitz Example
<div class="container">
<mat-card *ngFor="let item of data; let i = index" #panel [ngClass]="{expanded: expanded[i]}" [class.mat-elevation-z8]="expanded[i]">
<div class="header">
Some content here
<div class="toggle">
<button mat-icon-button>
<mat-icon *ngIf="!expanded[i]" (click)="expanded[i]=!expanded[i]">
edit
</mat-icon>
<mat-icon *ngIf="expanded[i]" (click)="expanded[i]=!expanded[i]">cancel</mat-icon>
</button>
</div>
</div>
<div class="body" *ngIf="expanded[i]">
Some content here
</div>
</mat-card>
</div>
Try this one. Use index instead of item.