How to show and hide div using Angular - html

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;
}

Related

Angular structural directive with CSS selector

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()"

JAWS reads labels of parent tags before reading first element

I am trying to fix an accessibility defect in an Angular project at work. When a page loads and I start to tab through the page, the first element that is visible in the form is read twice. My code is something like below
<form [formGroup]="form" role="form" attr.aria-label="Edit Form" novalidate>
<div class="form-row">
<div class="col-md-9 col-sm-12 col-lg-9 paddingLR0">
<!-- Hidden code not rendered due to ngIf=false -->
<div role="region" attr.aria-label="Edit button region" *ngIf="viewMode">
<!-- Hidden elements not rendered due to ngIf=false -->
<button *ngIf="isEditable" [disabled]="!canEdit" type="submit" (click)="enableEdit()">
Edit
</button>
<div class="back-header">
<a tabindex=0 (keyup.enter)="back()" (click)="back()" (mouseover)="changeBackIconOnHover('back-region-top')" (mouseout)="changeBackIcon('back-region-top')" id="back-region-top">
<img src="{{pathImg}}/back_black.png"
<span class="margin-left10">Back</span>
</a>
</div>
</div>
</div>
</div>
<!-- More code here -->
</form>
If you see the code the first element that is visible is the Edit button, nested in a div with role as region, which is in turn inside a form with role form. When I tab through the page instead of just reading the button just once Edit button JAWS reads Edit Form form region. Edit Button on first tab, then reads Edit button region. Edit Button. There are no tabindexes on the parent elements. Removing the role attribute and the corresponding labels does not work. How do I only make jaws read the edit button once?
The above problem was occuring because of an empty div which had a tabindex=0.
So in the code snippet above I had a commented line
<!-- Hidden code not rendered due to ngIf=false -->
That referred to multiple divs which are warning, success and error messages related to the form in my actual code. Each of those divs have an ngIf for conditional rendering and a tabindex=0 to make it tab accessible. Except one of those divs simply had a tabindex but no ngIf. So it was always rendered. Like below.
<div tabindex=0>
<div ngIf="condition"> {{errormessage}}
</div>
</div>
If JAWS tabs onto an empty element it reads the previous labels. I removed the outer div which was remaining empty and the problem is solved.

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>