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;
}
Related
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.
I need the answer to this question: is it possible to disable a mat-icon within a mat-tree-node?
So let me show you my code. Seeing the present mat-tree-node:
<mat-tree [dataSource]="ListView" [treeControl]="treeControl">
<mat-tree-node
*matTreeNodeDef="let node"
matTreeNodePadding
matTreeNodePaddingIndent="20"
class="mat-tree-node node-level-last hover"
>
<button class="cursor-default" mat-icon-button disableRipple="true"></button>
<div class="zone-action">
<div > {{ node.item.name }} </div>
<div class="icon-hover" *ngIf="!node.item.CanVisualize">
<div *ngIf="isEnabled">
<mat-icon
svgIcon="pencil"
color="primary"
(click)="actionReport(node.item, 'update'); $event.stopPropagation()"
></mat-icon>
</div>
</div>
</div>
</mat-tree-node>
I would like to have access to a list openened by the selection of a mat-tree-node, but I can't for the moment. So you have the property-binding " {{ node.item.name }} " that displays an information relative to the object selected which you need to know so as to proceed into the navigation of the component and it is needed to disable or hide the mat-icon inside <div *ngIf="isEnabled">.
But adding a structural directive like an ng-if in the HTML parent Node erase the node.item.name, printing an empty field, which behavior is clearly not the one searched.
Suggestion
<button mat-icon-button ngIf="isEnabled" (click)="actionReport(node.item, 'update'); $event.stopPropagation()">
<mat-icon>favorite</mat-icon>
</button>
<button mat-icon-button ngIf="!isEnabled" disabled>
<mat-icon>favorite</mat-icon>
</button>
https://material.angular.io/components/button/examples
Firstly, you should use a <button mat-icon-button> instead of the <mat-icon> directive:
<button mat-icon-button (click)="onButtonClick()">
<mat-icon>pencil</mat-icon>
</button>
vs
<mat-icon (click)="onButtonClick()">pencil</mat-icon>
Secondly, you can use the disabled input that the MatButton class (essentially a directive for button[mat-*-button]) exposes:
<button mat-icon-button [disabled]="isEnabled">
<mat-icon svgIcon="pencil"></mat-icon>
</button>
Note that the <mat-icon> directive does not support the disabled input.
I am currently working on a web application using angular and angular material. The page in question holds several profiles each with a button that when clicked removes the information currently showing and replaces it with the rest of the profile information. The issue is that when I click this button on one profile it does this information flip on all the profiles at once. I need help figuring out how to have the button only affect the profile it is associated with.
I am still relatively new to coding, so I've mainly been doing research on advice on how to approach this particular situation, but nothing I've found so far has worked.
<mat-card class="bpBuddyCont" *ngFor= "let profile of profileList">
<div>
<ul class="bpBuddies">
<li class="li2">
<div *ngIf="!showHiddenInfo">
<mat-card-title class="specifics">{{profile.dogName}}</mat-card-title>
<mat-card-subtitle class="subtitle">Owner ~ {{profile.ownerFirstName}}</mat-card-subtitle>
<mat-card-subtitle>Member Since {{profile.yearJoined}}</mat-card-subtitle>
</div>
<div class="column4" *ngIf="showHiddenInfo">
<span class="details4">Additional Notes: </span>
<span class="details3">{{profile.additionalNotes}}</span>
</div>
</div>
<button mat-button color="primary" class="btn" (click)="showHiddenInfo = !showHiddenInfo">{{showHiddenInfo ? 'Back' : 'More...'}}</button>
</li>
</ul>
</div>
</mat-card>
You can extend the profile object with
profile.showHiddenInfo and set it as false initially.
For this in your js(most probably the component file) after getting profileList,
profileList.forEach((profile, index) => {
angular.extend(profile, {showHiddenInfo: false});
//not sure about this angular.extend but you need to extend your object here
});
Now when the button is clicked replace showHiddenInfo, i.e.
profile.showHiddenInfo = !profile.showHiddenInfo;
And Replace
*ngIf="showHiddenInfo"
with
*ngIf="profile.showHiddenInfo"
You can do this using one boolean variable for each object, as profile.isExpanded and on click change it as like:
(click)="profile.isExpanded = !profile.isExpanded"
HTML Code:
<mat-card class="bpBuddyCont" *ngFor="let profile of profileList">
<div>
<ul class="bpBuddies">
<li class="li2">
<div *ngIf="!profile.isExpanded">
<mat-card-title class="specifics">{{profile.dogName}}</mat-card-title>
<mat-card-subtitle class="subtitle">Owner ~ {{profile.ownerFirstName}}</mat-card-subtitle>
<mat-card-subtitle>Member Since {{profile.yearJoined}}</mat-card-subtitle>
</div>
<div class="column4" *ngIf="profile.isExpanded">
<span class="details4">Additional Notes: </span>
<span class="details3">{{profile.additionalNotes}}</span>
</div>
<button mat-button color="primary" class="btn" (click)="profile.isExpanded = !profile.isExpanded">{{profile.isExpanded ? 'Back' : 'More...'}}</button>
</li>
</ul>
</div>
</mat-card>
No change in TS file.
WORKING STACKBLITZ
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!
I have a component that show/hide element by clicking a button.
This is my html
<div *ngFor="let history of histories | sortdate: '-dateModified'">
<p><b>{{ history.remarks }}</b> - <i>{{history.dateModified | date:'short'}}</i></p>
<a href="google.com"
[class.datatable-icon-right]="history.$$expanded"
[class.datatable-icon-down]="!history.$$expanded"
title="Expand/Collapse Row"
(click)="toggleExpandRow(history)"></a>
<!-- hide/show this by clicking the button above.-->
<div *ngFor="let step of history.steps; let i = index">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
<hr />
</div>
and my .ts
toggleExpandRow(row) {
console.log('Toggled Expand Row!', row);
//row
return false;
}
trying to search but, can't find any same sample.
On jquery, I can do this, but on Angular2, I am having hard time to figure this.
There are two options:
1- You can use the hidden directive to show or hide any element
<div [hidden]="!edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
2- You can use the ngIf control directive to add or remove the element. This is different of the hidden directive because it does not show / hide the element, but it add / remove from the DOM. You can loose unsaved data of the element. It can be the better choice for an edit component that is cancelled.
<div *ngIf="edited" class="alert alert-success box-msg" role="alert">
<strong>List Saved!</strong> Your changes has been saved.
</div>
Use the ngIf in your repeated rows. Create a boolean property called showStep to indicate whether the row should be expanded or not.
<div *ngFor="let step of history.steps; let i = index" ngIf="history.showStep">
<b>{{i+1}}.</b> {{step}}
<span class="clear"></span>
</div>
Then, in your .ts file:
toggleExpandRow(history) {
history.showStep = !history.showStep
//note the same porperty of showStep that is used in your html
}
Extra:
In fact, to save a few lines of codes, you don't even need the toggleExpandRow function at all. You can do it inline in your html:
//other attributes omitted for brevity
<a (click)="history.showStep = !history.showStep">