Angular structural directive with CSS selector - html

I am creating a custom dropdown menu.
The menu contains some items and should remain open when a user clicks on any of these items.
To check if the user clicks inside the dropdown menu I check via window.onclick if event.target.matches('dropdown-content *'). See the snippet below for context.
<div id="myDropdown" class="dropdown-content">
<div class="dropdown-grid">
<div class="add-offset">
<div class="dd-header">
<div (click)="setupNewCol()"><i class="fas fa-plus plus-sign"></i></div>
</div>
</div>
</div>
</div>
This works, but when I add *ngIf to the div with the function call the CSS selector 'dropdown-content *' doesn't seem to work anymore.
This is the HTML with the *ngIf
<div id="myDropdown" class="dropdown-content">
<div class="dropdown-grid">
<div class="add-offset">
<div class="dd-header">
<div *ngIf="!settingNewOffset; else offsetSelection" (click)="setupNewCol()"><i class="fas fa-plus plus-sign"></i></div>
<ng-template #offsetSelection>
<div (click)="addCol()">
CLICK ME
</div>
</ng-template>
</div>
</div>
</div>
</div>
With the introduction of the *ngIf in combination with ng-template the CSS selector doesn't recognize the clicks to be part of '.dropdown-content *' anymore. Why is this and what is a solution to this problem?

Why it won't register the click on target 'dropdown-content' is probably because now the clicked target is a div, that does not have 'dropdown-content'. Probably the target parent has that class, but not the target.
To check if a user clicks on any of the items. You already have methods addCol() or setupNewCol(). If this method runs then user has clicked some of the item where the method was attached. You could also just attach another method to the item e.g (click)="addCol(); onItemClick($event)"
onItemClick(event:any) {
console.log(event)
}
I don't see where the menu closing part is but using onItemClick you could just cancel that or try to cancel the event from propagating at all.
(click)="addCol(); event.stopPropagation()"

Related

How to show and hide div using Angular

I have a button and a div in a ngfor loop
and I want each button to be able to show and hide the div each time i click on it
the problem is that I don't already know the number of buttons and div it depends on the data in my database. just want every button to be responsible on the div next to it:
here is the code:
<div *ngFor="let par1 of lstUser1">
<button id="bt2" class="arrow2" (click)="arrowButton('bt2')">
my button
</button>
<div>
my div to show and hide
</div>
</div>
and here is an example of the design i'm trying to make
Yuo can use for show and hide div
*ngIf
<div *ngFor="let par1 of lstUser1">
<button id="bt2" class="arrow2"
(click)="changeMyDivStatus()">
my button
</button>
<div *ngIf="showMyDiv">
my div to show and hide
</div>
</div>
.ts file must have "showMyDiv" variable as boolean variable
changeMyDivStatus(){
showMyDiv = !showMyDiv;
}

Angular make part of component unclickable

So I have this component that is a button, which when clicked, navigates to a certain route. However, I want to put a button inside this, which doesn't make it navigate and does something else.
How do I do this? It is the follow/unfollow button.
<button type="button" class="btn" (click)='navigate()' *ngIf="searchResult.username"><mat-card>
<mat-card-header>
<mat-card-title>{{searchResult|null:['firstname']}} {{searchResult|null:['lastname']}}</mat-card-title>
</mat-card-header>
<mat-card-content class="container">
<div>{{searchResult|null: ['username']}}</div>
<div>
<!-- option to follow -->
<div *ngIf="!result.followers.includes(this.selfUsername)" class="follow">
<button mat-raised-button (click)="onFollow()">
Follow
</button>
</div>
<!-- already following -->
<div *ngIf="result.followers.includes(this.selfUsername)" class="follow">
<button mat-raised-button (click)="onUnfollow()">
Unfollow
</button>
</div>
</div>
<div>
<!-- dunno why these dont work -->
<!-- <p *ngFor="let item of searchResult|null:['history']">{{item}}</p> -->
</div>
<div>
<!-- <p *ngFor="let item of searchResult|null:['whishlist']">{{item}}</p> -->
</div>
</mat-card-content>
</mat-card>
</button>
Use button tags only when making interaction like calling functions that do something.
In your case you want to "hyperlink" somewhere (in this case it's a mat-card) and inside of if you want to place any buttons...let's say.
For navigation you should always use anchor tags like <a ... href="" or routerLink="">...content </ a>
So, just change the root <button ...> to <a ...>.....
and that should be it.
Like gsa.interactive said, you have to use a link for redirection.
With this logic you cannot have a clickable child button if it is located in a clickable parent element. You can't position these child buttons above the parent with z-index.
A child's z-index is set to the same stacking index as its parent.
2 possibilities:
you don't overlay the clickable link with the buttons.
Either you overlay them in the following way:add position: relative to the parent with a z-index 0 and add position : absolute to the buttons with z-index 1 with a specific position

how to hide vertical nav on click and display the corresponding content ( Navigation on mobile site with back button)

I have a mobile website, which is built as a single page application. I'm using angular to create a vertical menu, I want to hide the menu on menu item clicked and display its content container with a back button to go back to the menu.
first I have the main component with the menu and content container next to each other
main-component.html
<div class="container">
<div class="col-md-3 col-12 menu-container">
<app-menu-container></app-menu-container>
</div>
<div class="col-md-9 col-12">
<app-content-container></app-content-container>
</div>
</div>
menu.component.html to loop over menu items and display them
<div *ngFor="let menuItem of menu">
<app-menu-item [menuItem]="menuItem"> </app-menu-item>
</div>
menuItem.component that displays every menuItem. on item clicks, a subject will fire to open the corresponding content-container component
in the content-container component, I subscribed to get the item to open the content container
content-container.component.ts
subscribeToOpenContainer() {
this.subscriptionToOpenContainer = this.menuService.openMenuItemContainer.subscribe((menuItem) => {
this.menuItem = menuItem;
}
);
}
content-container.html
<ul>
<li>
<a class="document-type-icon"><i></i></a>
<div class="text-container">
<p class="document-name"></p>
<p class="last-update-date"> Last update date:</p>
<div class="line"></div>
</div>
<div class="action-icons-container">
<a class="delete-and-edit-icon"><i class="fa fa-trash"></i></a>
<a> <i class="fa fa-edit delete-and-edit-icon> </i>
</a>
</div>
</li>
<ul/>
I want the menu that is a single component to hide when a menu item is active and the content container is displayed with a back button to get back to the menu.
current approach
what I want to achieve on mobile screen size
This can be achieved using simple ngIf if you want to hide the sidebar using a click of button. If you want to hide the sidebar on clicking anywhere, you can use HostListener.
#HostListener('click', ['$event'])onClick(event) { });
You can get id of the element clicked using event.target.id. Use if logic to check which item was clicked and open the sidebar if not open already, and if it is open you can hide it by simply adding or remove css to the DOM.

How to disable click on <div> when <button> in <div> is clicked

I am using ReactJS with React-Bootstrap and am rendering the following content:
<div onClick={this.openModal.bind(this)} className="container">
<div className="content">
<div className="list">
...
</div>
<Button onClick={this.deleteContent.bind(this)}
className="delete-content">X
</Button>
<Modal show={this.state.showModal}
onHide={this.closeModal.bind(this)}
className="edit-content">
...
<Button onClick={this.closeModal.bind(this)}
className="close-modal">X
</Button>
</Modal>
</div>
<div>
In <div className="content">, I am rendering a set of components, and when you click on the <div className="Container">, it will open the Modal so you can edit the container's contents. There is a button to delete the container all together, which is inside the <div className="container">, as many containers will be rendered iteratively.
I am controlling whether the Modal is open with the component's state, where this.openModal() and this.closeModal() simply toggle a boolean that determines if the Modal should be shown (this.state.showModal).
My problem is: when I click the Button with className="delete-content" in the container, it also registers a click to open the Modal, because <div className="container"> has an onClick property. Thus, when I delete containers, the app gets stuck thinking the Modal is open, even though it's not.
My first idea to fix this is to move the onClick property from the <div className="container"> to <div className="list">, but I would like all of the space around the <Button className="delete-content"> to be clickable, and if I move it to list it will restrict the clickable area.
Is it possible to somehow implement when the delete-content Button is clicked to temporarily disable the onClick property of the <div className="container">? Or any other ideas/fixes?
It happens because of event propagation. To fix the problem you need to use stopPropagation on the event object.
handleDelete(event) {
event.stopPropagation()
this.deleteContent()
}
<Button
onClick={this.handleDelete.bind(this)}
className="delete-content">X
</Button>

Angular fire ng-click on row but not on href

I've made a page with bootstrap, and i would like to have an action when the user clicks on the row. This is easy, I put ng-click on the div that is the row.
However, inside the row elements I've a link, and I would like to avoid the firing of the ng-click when the user clicks on the link (in that case it should open the url of the link)
this is a picture of the row. Bascially if the use clicks anywhere except the link simbol it should filre the ng-click, if it clicks on the link simbol it should open the url.
is this possible?
PS: I tried to put ng-click on each item except the href element, but the href element is inside a column within other things, and if I don't put the ng-click on the column it will not fire if the use clicks on the empty space of the column.
<div class="col-sm-8" >
</i> |
<span class="h5 small">{{club.description}}</span>
</div>
$event.stopPropagation() on ng-click of anchor tag to bubble up event.
Markup
<div class="col-sm-8" ng-click="myMethod()">
<i class="fa fa-link"></i> |
</div>
You have to stop the event propagation from anchor to its parent div which has the click event handler.
<div class="col-sm-8" ng-click="onRowClick()">
</i> |
<span class="h5 small">{{club.description}}</span>
</div>
JS
$scope.onLinkClick = function (e) {
e.stopPropagation();
}
Try adding ng-click="$event.stopPropagation();" to your anchor tag
<i class="fa fa-link"></i>