Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm using angular materials and got struck while using mat-expansion. Whenever I click the buttons I've added on the expansion panel, it gets closed following the basic property of mat-panel.
Requirement - The panel should not contract on button click.
Use Case - In my case, I have multiple mat-expansion being stacked one on other and I'll be using the icon buttons to move the the expansion up/down in the stack. I've already written logic for move up/down but the issue is whenever I click the icon buttons, along with moving up/down, the expansion also perform the default behaviour of expansion/collision.
<mat-expansion-pannel>
<mat-expansion-panel-header>
<mat-panel-title class="title-align">
Image
</mat-panel-title>
<mat-panel-description>
<button mat-icon-button (click) ="moveUp(i)"><i class="material-icons md-18">arrow_upward</i></button>
<button mat-icon-button (click) ="moveDown(i)"><i class="material-icons md-18">arrow_downward</i></button>
<button mat-icon-button color="warn" (click) ="removeWidget(i)">
<i class="material-icons md-18">clear</i>
</button>
</mat-panel-description>
</mat-expansion-panel-header>
</mat-expansion-pannel>
As specified in the code, the panel should perform the move up and move down functionality. One way is we can disable any kind of button click on the panel, but since we need the functionality of buttons, I just want the buttons to work and don't want the panel to contract/expand unnecessarily.
I resolved this doubt as well , what we can do is pass $event in the button click function and then call stopPropogation() function .
<mat-expansion-panel class="mat-elevation-z8">
<mat-expansion-panel-header>
<mat-panel-description>
<button mat-icon-button (click)="moveUp($event,i)"><mat-icon>arrow_upward</mat-icon></button>
<button mat-icon-button (click)="moveDown($event,i)"><mat-icon>arrow_downward</mat-icon></button>
<button mat-icon-button (click)="removeWidget(i)" color="warn"><mat-icon>clear</mat-icon></button>
</mat-panel-description>
</mat-expansion-panel-header>
<div>
</div>
</mat-expansion-panel>
Also the function in typescript file :
moveUp(event : any, id : number) : void{
event.stopPropagation();
if(id > 0 ){
...
}
}
OK, I tried to suppress the expansion-contraction of the mat-expansion header, StackBlitz HERE.
I added [disabled]="clickButton" on each mat-expansion-panel and the action (click)="clickButton=false".
By default, clickButton: boolean = false; and when click on mat-expansion-panel, clickButton=false.
<mat-expansion-panel class="mat-elevation-z8" [disabled]="clickButton" (click)="clickButton=false">
<mat-expansion-panel-header>
<mat-panel-description>
<button mat-icon-button (click)="moveUp()"><mat-icon>arrow_upward</mat-icon></button>
<button mat-icon-button (click)="moveDown()"><mat-icon>arrow_downward</mat-icon></button>
<button mat-icon-button (click)="removeWidget()" color="warn"><mat-icon>clear</mat-icon></button>
</mat-panel-description>
</mat-expansion-panel-header>
<div>
<p>...</p>
</div>
</mat-expansion-panel>
It's in your functions that I added this.clickButton = true; thus allowing not to open the panel when clicking on one of the buttons.
moveUp(){
this.clickButton = true;
console.log("function()");
}
I hope this will help you.
DEMO:
Related
Lets say I have an ng-template like so:
<ng-template #templateRef>
<button
(click)="testClick()"
Click me
</button>
<a
I'm a link
</a>
</ng-template>
And then I want to use it in my html template like
<ng-container
[ngTemplateOutlet]="templateRef"
[ngTemplateOutletContext]="asdf"
>
</ng-container>
Is there any way for me to pass one additional variable into the template so that depending on where I use the template in the html, I can pass a different string that I can use to set the value of a custom directive via property binding? IE I really want the end result to be
<button
(click)="testClick()"
[customLocation]="top"
Click me
</button>
<a
[customLocation]="top"
I'm a link
>
</a>
and
<button
(click)="testClick()"
[customLocation]="bottom"
Click me
</button>
<a
[customLocation]="bottom"
I'm a link
>
</a>
So when I use the template like
<ng-container
[ngTemplateOutlet]="templateRef"
[ngTemplateOutletContext]="asdf"
>
</ng-container>
I just want to leave everything that's currently there as-is and pass one more variable into the container that will get put as the value for customLocation. Can this be done? Any help is appreciated
templates have a context. Here we create a template variable named location thanks to the syntax let-location. The variable will be binded to the $implicit property of the context.
<ng-template #templateRef let-location>
<button
[customLocation]="location"
</button>
</ng-template>
<ng-container
[ngTemplateOutlet]="templateRef"
[ngTemplateOutletContext]="{$implicit: 'top'}"
>
</ng-container>
Note that it's possible to have template variables by naming them. It's explained in https://angular.io/api/common/NgTemplateOutlet.
have an issue with the expansion of the accordion containing a list of items using a keyboard.
There is a complication in that all the accordion's data is being populated from an API, so a lot of the solutions that I had seen are hardcoded. For example, using the information found in the article below didn't work as the unique values are hard coded:
https://www.hassellinclusion.com/blog/accessible-accordion-pattern/
I've added in a lot of the appropriate ARIA labels and navigating via tab around it works well as does the screen reader, but I can't get the accordion to expand.
I tried to talking it from another angle by getting the enter button to be interpreted as a click on the element to expand the accordion but got completely lost trying to do such a thing in Angular as inserting Vanilla JS is not as straight forward as it would seem.
Here is the code, it's spread over three components so I've compiled into one and removed some styling classes for legibility:
<div tabindex="0" (keydown.enter)="myFunction()" role="button">
<h2 tabindex="0">
<img>
<i tabindex="0"></i>{{ organiser.name }}
</h2>
//this component displays the selected item. the accessibility on this works fine
<app-selected-area role="region">
</app-selected-area>
</div>
<div class="content">
//this component displays the items that can be selected
<app-skill-item class="item">
<div tabindex="0" role="button">
<h3>{{ skill.name }}</h3>
<button *ngIf="updateable && isSelected()" (click)="select()">
Remove
<span class="screen-reader-only">
{{ skill.name }}
</span>
skill
</button>
<button *ngIf="updateable && !isSelected()" (click)="select()" tabindex="0">
Add
<span class="screen-reader-only">
{{ skill.name }}
</span>
skill
</button>
</app-skill-item>
</div>
Any help or hints would be much appreciated!
Ended up finding the answer for this in the follow question/thread:
Trigger click in Typescript - Property 'click' does not exist on type 'Element'
let element: HTMLElement = document.getElementsByClassName('btn')[0] as HTMLElement;
element.click();
this was the following code that let me manipulate the accordion via the enter key as a click
I have a Virtual scroll feature on my website. Every item in virtual scroll is expansion panel with different count of lines within. When I implement <cdk-virtual-scroll-viewport> expansion panels are rendered fine, but when I click on current panel it not expand and only increase his height with maybe 5 px. I don't know how to do it, that expansion panel will expand properly.
I've tried to move expansion panel to <ng-container> but id didn't help.
<div class="container">
<mat-card>
<mat-card-title>
<span class="panelItem">Id</span>
<span class="secondPanelItem">Name</span>
<span class="lastPanelItem">Version</span>
</mat-card-title>
</mat-card>
<cdk-virtual-scroll-viewport itemSize="50" class="viewport">
<mat-accordion>
<ng-container *cdkVirtualFor="let description of allDescriptions">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
<span class="panelItem">{{description.id}}</span>
<span class="secondPanelItem">{{description.name}}</span>
<span class="lastPanelItem">{{description.version}}</span>
</mat-panel-title>
</mat-expansion-panel-header>
</mat-expansion-panel>
</ng-container>
</mat-accordion>
</cdk-virtual-scroll-viewport>
</div>
I finally found where was problem. I was setted in scss file height of expansion panel to 50 px so It can't expand more. When I removed this everything is OK.
I recently started using angular-material and am struggling/unsure about opening/closing a mat-menu... I see in the examples on the angular-material documentation site that they assign an id to the menu and then apply a directive to the button that is used to toggle the menu. e.g. [matMenuTriggerFor]="menu"
How can I go about writing a directive that does that? I'm not sure how to pass a reference to a specific menu to a directive that then calls the toggle() method on the DOM element with that id?
The following code produces the errors:
Can't bind to 'matMenuTriggerFor' since it isn't a known property of 'button'.
There is no directive with "exportAs" set to "matMenu".
My code:
<li>
<button mat-icon-button [matMenuTriggerFor]="stockSystemMenu">
<mat-icon class="sn-item">
<i class="material-icons">archive</i>
</mat-icon>
</button>
<span class="sn-item" (click)="toggleMenu(stockSystemMenu)">Stok System</span>
<mat-menu #stockSystemMenu="matMenu">
<button mat-menu-item>
<mat-icon>
<i class="material-icons">chevron_right</i>
</mat-icon>
<span>Service 1</span>
</button>
</mat-menu>
</li>
There is confusion because Material introduced a breaking change as I understand it.. See material 2 Changelog - Breaking Changes
Starting with Material 2.0.0-beta.12. Use mat instead of md-*.. Seems only some of the docs at material.angular.io are updated with mat. Specifically, if you click view source and see md, I believe they have yet to replace it with mat.
So either update to Material 2.0.0-beta.12 and use mat-*, or use md-*.
"Your code is correct, you don't need to write matMenuTriggerFor directive, it is part of the API, make sure you have imported the MatMenuModule, MatButtonModule, and MatIconModule into your app module." - from comments
I have a View/View-Model pair that implements a popover custom attribute. My specific goals include dismissing the popover upon both button click within the popover itself, and from clicking anywhere else on the page.
I can get my doSomething() VM function to work on the element level in the view, but not within an attribute containing an element. I've explained the issue further in the code comments. I'd appreciate some guidance. Thanks!
blog.html
<template>
<require from="../popover/popover"></require>
...
<!-- doSomething() works here! -->
<button type='button' click.trigger='doSomething()'>ClickMe</button>
<!-- doSomething() does not work here! -->
<!-- `click.trigger`/`click.delegate` does not trigger anything, while `onclick` shows
"Uncaught ReferenceError: doSomething is not defined" -->
<span class="glyphicon glyphicon-star" popover="title.bind: blogpost.title; placement.bind: 'top'"
data-content='<button type="button" click.trigger="doSomething()">ClickMe</button>' ></span>
...
</template>
blog.ts
...
doSomething() {
console.log('doing something');
}
popover.ts
...
bind() {
$(this.element).popover({
title: this.title,
placement: this.placement,
content: this.content,
trigger: 'click',
html: true
});
}
I recently went through the same problem. I'm currently working on a Bootstrap port for Aurelia, it is not done yet, and I haven't written any documentation, but the popover is already implemented.
You are more than welcome to take a look:
https://github.com/tochoromero/aurelia-bootstrap/tree/master/src/popover
The way you are trying to implement the popover is going to be very complicated (if even possible), things are going to get messy with the scopes. If you only had text then it would be fine, but you basically want to be able to put anything in the popover and have it bound to the right View-Model.
The way I solved this was having a couple of Custom Elements that represent the popover, I have AubsCustomPopover, AubsPopoverTitle and AubsPopoverContent.
With this 3 custom elements you will create the bootstrap markup for the popover, and because you are adding them directly in the view they will have the right View-Model, and you can do whatever you want inside them.
And then, there is a custom attribute, this is AubsPopover, this is the one that will be in charge of showing and hiding the custom attribute depending on the trigger action you specify (hover, click, focus, outsideClick).
The code using it looks something like this:
<aubs-custom-popover model.bind="customPopover">
<aubs-popover-title>
This is my awesome title <i class="fa fa-star"></i>
</aubs-popover-title>
<aubs-popover-content>
<div class="form-group">
<label for="exampleInputPassword1">Password</label>
<input type="password" class="form-control" text.bind="password"
placeholder="Password">
</div>
<button class="btn btn-default" click.delegate="isOpen = false">
Close
</button>
</aubs-popover-content>
</aubs-custom-popover>
<button class="btn btn-primary"
aubs-popover="custom-model.bind: customPopover;
trigger: outsideClick;
position: bottom;
open.bind:isOpen">
Custom Popover
</button>
As I said the Popover is fully implemented but I haven't written any documentation, I want to have a couple of more components before I do that.
If you want to use it, I can give you some help setting it up.