Angular access DOM sibling element to alter css class - javascript

How do I gain access to the respective sibling element of my button from the ngFor iteration on my collection?
Dom Element, I'm attempting to access this DOM element, so I can alter the sibling element div.popup class. As shown in the Codepen example linked at the bottom of the post.
I'm very new with angular, please advise.
<button
#popBtn
href="#"
id="info"
class="info popup-trigger"
title="info"
(click)="PopUp($event)"
>
Popup
</button>
Prior to the posting here, I read on the following articles but I couldn't understand completely or relate to it.
Pass a reference to DOM object with ng-click
how to get DOM element with ng-click
How to get the element html clicked in a ngFor to add a css class?
Overview of code
Component.html
<section class="ArticlesGrid">
<div *ngFor="let article of articles" class="windowsBox">
<article class="ui-titlebar">
<h4 class="ui-titletext">{{article.title}}</h4>
</article>
<div class="windowsScreen">
<button
#popBtn
href="#"
id="info"
class="info popup-trigger"
title="info"
(click)="PopUp($event)"
>
Popup
</button>
<div class="popup" role="alert">
<div class="popup-container">
Close
<p>{{article.content}}}</p>
</div>
</div>
</div>
<p class="windowsTech">
Technologies:
<span class="THtml"></span>
<span class="TCss"></span>
<span class="TJs"></span>
</p>
</div>
</section>
Component.ts
PopUp(event: Event) {
//console.log(this.viewBtn.nativeElement.nextElementSibling.classList.toggle("is-visible"));
console.log(event);
// this.viewBtn.nativeElement.
}
SandBox Mockup
https://stackblitz.com/edit/angular-collection-popup?file=src/app/app.component.html
Function to mirror
https://codepen.io/Gugiui/pen/vweXYR
Thanks for reading my question. I hope you can advise/guide me

add template reference variable on popup div -
<div class="popup" role="alert" #popupDiv>
pass it in button click function -
(click)="PopUp($event, popupDiv)"
change class in PopUp method using plain javascript -
PopUp(event: Event, element) {
element.classList.remove('popup');
element.classList.add('test');
console.log(element.classList);
}

Related

Message won't display a second time after being closed

User can click the help icon to display a help message. It will close if the user clicks on the close icon in the message. This can be repeated an indefinite amount of time.
This works if both the help icon and the message with the close icon are inside the ng-controller.
However, if the help icon is outside and the message is inside it (see below), then I can display and close the help message, but it won't work if I try to display it a second time.
What am I missing?
<div ui-content-for="title">
<span>Page Title</span>
<span>
<i ng-click="isHelpVisible = true;" class="fa fa-question-circle">
</i>
</span>
</div>
<div ng-controller="InventoryController as inventory">
<div class="scrollable">
<div ng-show="isHelpVisible" class="alert alert-info alert-dismissible">
<a class="close" ng-click="isHelpVisible = false;"
aria-label="close" data-dismiss="alert">×</a>
Help message is here.
</div>
</div>
</div>
This is a data hiding problem caused by the fact that the ng-controller directive creates a child scope.
Instead of setting a scope property directly, set a property of an object on the parent scope.
<div ui-content-for="title">
<span>Page Title</span>
<span><i ng-click="help={isHelpVisible: true}" class="fa fa-question-circle"></i></span>
</div>
<div ng-controller="InventoryController as inventory">
<div class="scrollable">
<div ng-show="help.isHelpVisible" class="alert alert-info alert-dismissible">
<a class="close" ng-click="help.isHelpVisible=false;"
aria-label="close" data-dismiss="alert">×</a>
Help message is here.
</div>
</div>
</div>
Scope inheritance is normally straightfoward... until you need 2-way data binding.
If you try to bind to a primitive (e.g., number, string, boolean) in the parent scope from inside the child scope. It doesn't work the way most people expect it should work. The child scope gets its own property that hides/shadows the parent property of the same name.
Your workaround is to define objects in the parent for your model, then reference a property of that object in the child.
For more information, see
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

How do I change a variable in a child element that has ng-click in the parent element.

Consider this code:
<section class="page-section about-us" scroll-bookmark="about-us" ng-click="activeSection=true" ng-init="activeSection=false">
<div class="page-content sub-content active-section">{{activeSection}}
<div class="page-border">
<a href="#" class="close-section"><img src="public/images/go-back-icon.png" />
<div class="back-button" ng-click="activeSection=false">CLOSE</div>
</a>
</div>
</div>
</section>
I have an ng-click in the that element which changes the value of 'activeSection' to true. Inside of it, I have another button that can switch this back to it's initial value (false).
In the actual app, it would show or hide this child button based on a class added to the element,just to give you a little background what I'm trying to achieve.
When I click on the element, it does as I expect it to be: switch the value to 'true'. But when I click on the .back-button element with the other ng-click, it fails to register the changed value.
Why is that?
They're both inside the same controller, btw. If there's a solution that doesn't involve creating a new controller, it would be better.
If you click on your back button, activeSection will be false but then your event will be propagated to its parent so the ng-click of Section will be executed too and activeSection will be true again.
In order to make your code work, you should stop the propagation of the ng-click event after changing the value of your variable in your back-button.
Your code would look like this:
<section class="page-section about-us" scroll-bookmark="about-us" ng-click="activeSection=true" ng-init="activeSection=false">
<div class="page-content sub-content active-section">{{activeSection}}
<div class="page-border">
<a href="#" class="close-section"><img src="public/images/go-back-icon.png" />
<div class="back-button" ng-click="activeSection=false; $event.stopPropagation();">CLOSE</div>
</a>
</div>
</div>
</section>
What you are doing wrong is that you are putting the close button inside the element which have already ng-click, that's why when you are clicking the close button, it executes the parent ng-click and stop propagation for all other click events happening simultaneously.
So, the possible solution is making another super parent of the elements and taking the close button out of the element which is making it visible when clicked and adding a ng-show directive to the close button.
Checkout the following snippet
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<section class="page-section about-us" scroll-bookmark="about-us" ng-init="activeSection=false">
<div ng-click="activeSection=true" class="page-content sub-content active-section">{{activeSection}}
<div class="page-border">
<a href="#" class="close-section"><img src="public/images/go-back-icon.png" />
</a>
</div>
</div>
<div ng-show="activeSection" class="back-button" ng-click="activeSection=false">CLOSE</div>
</section>
</div>

Removing the whole div with JavaScript [duplicate]

This question already has answers here:
Remove element by id
(19 answers)
Remove parent div by class name - jquery
(5 answers)
Closed 6 years ago.
Before you mark this as a duplicate, this is how my question is different.
Due to the lack of content actually on google, all that I can find is
removing the parent ID, I don't think that applies as the parent ID
would only remove panel-body, then leave panel-heading and the panel
div there.
I wanted to ask a quick question that I couldn't find any help with online. I have a bootstrap panel, which has two div's insdie of it, one for the panel-header and one for the panel-body. Inside the panel-body div I have a btn btn-success button that I want to remove the whole panel on click.
<div id="draggable" class="habbo-notification panel panel-default">
<div class="panel-heading">
Panel Header
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-4">
<font color="#B00049">
<h1 style="font-size:144px;margin-top:0;margin-left:14px;"><i class="fa fa-globe fa-6" aria-hidden="true"></i><h1>
</font>
</div>
<div class="col-md-8">
<p>
Some content here
</p>
<br>
<div class="btn btn-success" onclick="" style="width:100%">Close this</div>
</div>
</div>
</div>
</div>
</div>
In javascript or jquery (don't mind which one), how could I remove the entire div onclick of the button, without knowing the ID or class, or having any access to the panel div at all. I declare the panel-body's content somewhere other than the place where I declare the panel and it's two divs panel-body and panel-header.
I want to remove the whole panel div that the button is assigned to, on click?
<div class="btn btn-success" onclick="" style="width:100%">Close this</div>
Can anyone help?
The jQuery method is this one-liner.
$('.btn-success').on('click', function(){
$(this).closest('div.panel').remove();
});
The .closest() function looks for the nearest parent matching the supplied selector. In this case, it checks each parent of this until it sees div.panel.
You could drop this in your onclick="", though onevent attributes are deprecated in HTML. Standards expect events to be set within the Javascript.
I don't really get why you can't use the class(es) of the panel div like .panel, for example:
$(".btn").click(function(){
$(".panel").css("display","none");
});
But I think this would technically also work:
$(".btn").click(function(){
$(this).parent().parent().css("display","none");
});

Selecting nested elements

I have a page hierarchy like this:
<div class="panel" attribute-id="1">
<button class="delete">
<div class="panel" attribute-id="2" association-id="20">
<button class="delete">
</div>
</div>
....
So I have a bunch of these panels with nested panels inside, and I'm trying to create on on click handler for the delete buttons of the top level panels only (so the ones immediately inside panels that do not have an association id). The only different between the parent and child panels is that the child ones have the extra attribute "association-id".
So I can select the top level panels only like so:
$('.panel[attribute-id]:not([association-id]')
But if I try to get the delete buttons from from these like:
$('.panel[attribute-id]:not([association-id] .delete')
Obviously I'm still going to get the child buttons.
I can't modify the html in anyway, how could I go about doing this?
$(':not(.panel[attribute-id][association-id]) > .delete')
seems to do the trick.
jsfiddle
I've changed .panel-group to .panel to get it to work with the HTML provided.
Wrap them all in a div and assign that div a unique class. Then you can use jquery selector ".panel-group > .panel" to get only direct children of top level.
<div class="panel-group">
<div class="panel" attribute-id="1">
<button class="delete">
<div class="panel" attribute-id="2" association-id="20">
<button class="delete">
</div>
</div>
<div class="panel" attribute-id="11">
<button class="delete">
<div class="panel" attribute-id="12" association-id="120">
<button class="delete">
</div>
</div>
</div>
You can use the children method:
$('.panel-group[attribute-id]').children('button').first()

jQuery Select Dynamically Content

I have a page which contain dynamic content.
<div id="content-1">
<div id="subcontent-1"></div>
<i id="delete-1"></i>
</div>
.
.
.
<div id="content-10">
<div id="subcontent-10"></div>
<i id="delete-10"></i>
</div>
How to select dynamic content with jQuery selectors and how to understand which content will be deleted I'm not sure and confused.
Need to understand which delete for clicked by user.
In your markup, it will be easier to select elements if you can add a class to them like
<div id="content-1" class="content">
<div id="subcontent-1"></div>
<i id="delete-1" class="delete">i</i>
</div>
then use the class selector to register the event handlers
$(document).on('click', '.content .delete', function(){
$(this).closest('.content').remove();
})
Event binding on dynamically created elements?

Categories