When adding pills with horizontal orientation, div height doesn't increase correctly - html

I'm working on a web application, and I have a datatable where you can filter via an API call. Upon adding filters, Material Design chips get added in horizontal orientation. When I add too much chips, my text in my div goes over the text above it.
This is my code:
<!-- ABOVE IS ANOTHER MAT TOOLBAR ROW WITH 3 INPUTS AS SHOWN IN THE PICTURE BELOW -->
<mat-toolbar-row class="controls">
<div class="col-md-9">
<span>Filtering {{getTotalDataSize()}}
<span *ngIf="type === 'user'" i18n>users</span>
<span *ngIf="type === 'role'" i18n>roles</span>
<span *ngIf="type === 'entitlement'" i18n>entitlements</span>
<span *ngIf="type === 'application'" i18n>applications</span>:</span>
<span *ngIf="clusterConditions.length == 0"> no filters applied</span>
<div *ngIf="clusterConditions.length > 0 || isInGroupByMode()">
<mat-chip-list>
<mat-chip *ngFor="let condition of clusterConditions" [selectable]="false" [removable]="true" (removed)="removeCondition(condition)">
<span *ngIf="condition.attr.name">{{condition.attr.name | capitalize}} {{condition.match}} "{{condition.val}}"</span>
<span *ngIf="!condition.attr.name">Contains "{{condition.val}}"</span>
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
<mat-chip *ngIf="isInGroupByMode()" [selectable]="false" [removable]="true" (removed)="changeGroupByMode(false)">
<span>Grouped by {{groupByAttribute.name}}</span>
<mat-icon matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
</div>
</div>
<div class="col-md-3">
<mat-paginator #paginator [length]="getDataSize()" [pageIndex]="0" [pageSize]="10"></mat-paginator>
</div>
</mat-toolbar-row>
I tried fiddling with some display: block/flex; and box-sizing: border-box;, but I can't seem to figure it out!
An example of what it looks like when adding too much chips:
I'd like the 'Filtering ...' to show beneath the input fields!
EDIT: Wanted behaviour:
Note: The row has two columns, the chips column and the navigator on the right. When there are to much pills, a next row has to start as shown in the picture above, in the column div of the pills, not of the paginator.
Either the pills start next to the 'Filtering ... :' or beneath it (doesn't really matter)
Thanks in advance!

Related

How to hide something when no search result found in angular

In my homepage I have a search bar and a list of user favorite cards. Only If there is no favorited cards on the initial browser load and when a user removed all their favorite cards then it'll show a banner "Add a favorite...".
The problem I have right now is the banner is displaying when I search something on the search-bar and found no favorited card. How do I fix that?. I don't want to show my banner if there is no search result found.
If I do favorites.size == 0 instead then the banner is not showing up at all when browser load or user removed all their cards.
<div class="input">
<form class="search-form">
<input #searchValue id="input-field" class="input-field" type="search"
name="insightSearchFilter" (ngModelChange)="filterChanged($event)" [formControl]="inputCtrl"/>
<p class="hint" *ngIf="inputCtrl.value">
<strong> {{ favorites?.length }} Search Result for </strong><em>"{{ inputCtrl?.value }}".</em>
<strong> The Results listed below are exact matches for your query.</strong>
</p>
</form>
</div>
<div *ngIf="favorites">
<div *ngIf="favorites.length > 0">
<app-card-list [cards]="favorites"></app-card-list>
</div>
<div *ngIf="favorites.length == 0" class="empty-faves-container">
<div class="add-faves-container">
<div class="add-faves-ico"></div>
<div class="text">Add a Favorite</div>
</div>
</div>
</div>
Since you are filtering this.favorites in filterChanged methods. You should apply check for search text also along with length check.
like
(favorites.length == 0 && !(inputCtrl.value))

how to style a selected mat-button in an angular application

I have an Angular application where the user has multiple choices with buttons and when a button is pressed another component will display. The component depends on the user's choice.
One thing I'm trying to implement is the styling of the buttons to make it clear which choice has been selected.
<div fxLayout="row" fxLayoutAlign="space-between center" fxFill>
<div *ngFor="let button of buttons">
<button
mat-stroked-button
*ngIf="button.type === 'button'"
(click)="buttonPressed()"
ngxScrollTo
>
{{ button.text }}
</button>
</div>
<div fxLayout="row" fxLayoutAlign="space-between center">
<div *ngIf="item.hasSomeProperty | isTypeButton">
<button mat-mini-fab (click)="buttonPressed()">
<mat-icon>close</mat-icon>
</button>
</div>
</div>
I have also attached a picture of what im trying to achieve here:
Any help would be much appreciated.
Simply use [ngClass] or [ngStyle]:
<div *ngFor="let button of buttons">
<button
mat-stroked-button
*ngIf="button.type === 'button'"
[ngClass]="{'disabledButton': !button.selected}"
(click)="buttonPressed(button)"
ngxScrollTo
>
{{ button.text }}
</button>
</div>
Assuming that your button model contains the "selected" property (or you have some other model storing information which button was actually clicked):
buttonPressed(button: Button) {
// Mark only button as selected
this.buttons.forEach(b => b.selected = b === button);
}
And of course add some class in the css:
.disabledButton {
opacity: 0.75;
}
Note - writing this from top of my head (since no stackblitz was provided) so some adjustments might be needed.

Angular 10 - Prevent carriage returns from adding spaces at beginning and end of text literal rendered into HTML

I'm writing an application where spacing is critical in the output of some of the text I'm rendering. Users are allowed to highlight text with their mouse, then click a button to "mark" the text. I then later re-render the output with text highlighted that has been marked. I recently noticed an off-by-one issue when doing this though and, when looking at the rendered HTML I could see the problem.
This code
<mat-card (mouseup)="mouseUp()" #card>{{article.text}}</mat-card>
Produces this result in the HTML
Whereas this code
<mat-card (mouseup)="mouseUp()" #card>
{{article.text}}
</mat-card>
Produces this result in the HTML
There's a space at the beginning and the end of the text literal in the version with the carriage return in it but I have a couple of issues when trying to remove the carriage return. Firstly, the part of the code where I display the text again with the highlighting shown is much more complex, making it so I can't simply change the carriage returns around. It looks like this.
<mat-card class="te-card">
<ng-container *ngFor="let textGroup of article.textSets; index as i; first as isFirst; last as isLast" >
<ng-container *ngIf="isFirst || article.textSets[i].rangeStart > article.textSets[i - 1].rangeEnd">
{{article.text.substring(i === 0 ? 0 : article.textSets[i - 1].rangeEnd, article.textSets[i].rangeStart)}}
<div class="grouped-text-tab">
<span [ngClass]="{ 'contributed': markExistsForUserAndType(article.textSets[i].textSetId, 'one')}">1 ({{(article.textSets[i].markMetrics || {"oneCount": 0}).oneCount}})</span> |
<span [ngClass]="{ 'contributed': markExistsForUserAndType(article.textSets[i].textSetId, 'two')}">2 ({{(article.textSets[i].markMetrics || {"twoCount": 0}).twoCount}})</span> |
<span [ngClass]="{ 'contributed': markExistsForUserAndType(article.textSets[i].textSetId, 'three')}">3 ({{(article.textSets[i].markMetrics || {"threeCount": 0}).threeCount}})</span>
</div>
<span class="claim grouped-text" [matMenuTriggerFor]="contribute" [matMenuTriggerData]="{textSetId: article.textSets[i].textSetId}" (click)="setActiveGroupIndex(i)">
{{article.text.substring(article.textSets[i].rangeStart, article.textSets[i].rangeEnd)}}
</span>
<ng-container *ngIf="isLast">
{{article.text.substring(article.textSets[i].rangeEnd, article.text.length)}}
</ng-container>
</ng-container>
</ng-container>
</mat-card>
In order to format my code to remove carriage returns I would have to add unwanted spacing at the beginning or end, I'd have to turn this well-structured code into something less readable like what you see below. Note that the grouped-text-tab div has been moved up to be at the end of the previous line. (FYI: everything in grouped-text-tab doesn't contain content sensitive to this issue because I won't be highlighting any of that text and have thus left the carriage returns inside that div intact):
<mat-card class="te-card">
<ng-container *ngFor="let textGroup of article.textSets; index as i; first as isFirst; last as isLast" >
<ng-container *ngIf="isFirst || article.textSets[i].rangeStart > article.textSets[i - 1].rangeEnd">{{article.text.substring(i === 0 ? 0 : article.textSets[i - 1].rangeEnd, article.textSets[i].rangeStart)}}<div class="grouped-text-tab">
<span [ngClass]="{ 'contributed': markExistsForUserAndType(article.textSets[i].textSetId, 'one')}">1 ({{(article.textSets[i].markMetrics || {"oneCount": 0}).oneCount}})</span> |
<span [ngClass]="{ 'contributed': markExistsForUserAndType(article.textSets[i].textSetId, 'two')}">2 ({{(article.textSets[i].markMetrics || {"twoCount": 0}).twoCount}})</span> |
<span [ngClass]="{ 'contributed': markExistsForUserAndType(article.textSets[i].textSetId, 'three')}">3 ({{(article.textSets[i].markMetrics || {"threeCount": 0}).threeCount}})</span>
</div>
<span class="claim grouped-text" [matMenuTriggerFor]="contribute" [matMenuTriggerData]="{textSetId: article.textSets[i].textSetId}" (click)="setActiveGroupIndex(i)">{{article.text.substring(article.textSets[i].rangeStart, article.textSets[i].rangeEnd)}}</span>
<ng-container *ngIf="isLast">{{article.text.substring(article.textSets[i].rangeEnd, article.text.length)}}</ng-container>
</ng-container>
</ng-container>
</mat-card>
But that's not even the biggest problem I see because if someone just tells their code editor to auto format the code, the functionality will actually break. I see this as the biggest issue really. Functionality actually dependent on code layout.
So, I'd like to find a cleaner way to do this. The reason I'm tagging Angular in the title and keywords is because, although this is an HTML issue, if I didn't have Angular involved in the mix <pre></pre> would possibly be an OK solution. However, with the complexity of my second example and with Angular in the mix, I can't really use that as an option.
I've also tried using the following CSS directives on the mat-card element to no avail.
whitespace: pre;
whitespace: pre-wrap;
whitespace: pre-line;
Faced a similar problem on Angular 9. As a result, I was able to decide as follows:
<mat-card (mouseup)="mouseUp()" #card [innerHTML]="article.text">
</mat-card>

Angular - Changing a components style depending on ngIf result

I have a mat-card that essentially has two columns inside of it; one column for displaying the image and the other for the mat-card contents. I currently set the two columns widths to half of their containers width to equally space them inside of the mat-card.
I am trying to modify my html code so that if the returned image path is empty, the mat-card contents occupy the entire width of the mat-card. I've tried doing so using the [ngClass] below but couldn't get it to work.
Is there an alternate way of doing this?
Below is my html code, I set the width of the two columns to half their containers width in the css file.
<mat-card class="mat-elevation-z1" id="card-div" >
<div class="img-container" *ngIf="blog.imagePath != ''" [ngClass]="blog.imagePath === '' ? 'width': '0%'">
<img [src]="blog.imagePath" [alt]="">
</div>
<div class="card-content" [ngClass]="blog.imagePath === '' ? 'width': '80%'">
<mat-card-header>
<mat-card-title> {{ blog.title }}</mat-card-title>
<mat-card-subtitle>
Published: {{blog.dateCreated}} <br>
Author: {{blog.author}}
</mat-card-subtitle>
</mat-card-header>
<hr>
<mat-card-content>
<p >{{ blog.content }}</p>
<mat-action-row >
<button mat-raised-button *ngIf="adminIsAuthenticated" (click)="onDelete(blog.blogId)">Delete</button>
<button mat-raised-button *ngIf="adminIsAuthenticated" [routerLink]="['/edit', blog.blogId]">Edit</button>
<button mat-raised-button >Read More</button>
</mat-action-row>
</mat-card-content>
</div>
</mat-card>
The [ngClass] helps you to add some CSS classes to an element, while in your code you are trying to add width property that is set to 80%.
If you wanna use a [ngClass] then you can write it like so
[ngClass]="{ yourClassName: blog.imagePath === ''}"
and in CSS or SCSS file specify this class like so
.yourClassName {
width: 80%;
}

mwlDraggable (Drag & Drop) - minimum length of move

I have a problem with mat-card, that is draggable and also contains some button. Unfortunately, on my PC button (click) don't work at all, on my collegue it works sometimes. We think that it can be caused as click is treated as dragging element. Is there anyway to set minimal length of move (dragging), which causes starting treating object as moved?
It was tested on 2 machines - the same code, different behaviour - one one (click) on button is never executed, on second one - sometimes.
What I found now on my computer - while I'm debugging it (Chrome) - when I move my mouse cursor over cards on one of cases occurring this - I get blue "shadow" over the whole app from debugger, but button is clickable - it works as I expected, otherwise - not.
<mat-card mwlDraggable *ngFor="let item of items; let i = index" [dragActiveClass]="'field-dragged'"
[dropData]="item" (dragEnd)="itemFieldDragEnd($event, item)">
<mat-card-content>
<div class="pull-left m-t-5">
{{item.name}}
<div class="field-meta truncate">
{{item.desc}}
</div>
</div>
<div class="pull-right">
<button mat-icon-button (click)="onItemFieldClick($event, item)" matTooltip="somehint">
<mat-icon class="md-24">arrow_forward_ios</mat-icon>
</button>
</div>
</mat-card-content>
</mat-card>
I want to obtain way to force mwlDraggable to become draggable only if it was moved really by let's say 10px, not before. Or any other solution that would work for that problem.
I found solution on github: https://github.com/mattlewis92/angular-draggable-droppable/issues/53
Exemplary fully implemented solution using above:
<mat-card mwlDraggable *ngFor="let item of items; let i = index" [dragActiveClass]="'field-dragged'"
[dropData]="item" (dragEnd)="itemFieldDragEnd($event, item)"
[validateDrag]="dragThresholdValidator">
<mat-card-content>
<div class="pull-left m-t-5">
{{item.name}}
<div class="field-meta truncate">
{{item.desc}}
</div>
</div>
<div class="pull-right">
<button mat-icon-button (click)="onItemFieldClick($event, item)" matTooltip="somehint">
<mat-icon class="md-24">arrow_forward_ios</mat-icon>
</button>
</div>
</mat-card-content>
</mat-card>
public dragThresholdValidator({ x, y }: any): boolean {
const min_drag_threshold = 5;
return Math.abs(x) > min_drag_threshold || Math.abs(y) > min_drag_threshold;
}