How to get reference to current element in Angular 2? - javascript

For example I have a function itemDragged(). How inside that function to get a reference of ion-item-sliding to get its current class attribute?
<ion-item-sliding *ngFor="let activity of activities" (click)="showModalInfo(activity)" (ionDrag)="itemDragged($event)">

You can use reference variable in template
<ion-item-sliding #iis *ngFor="let activity of activities" (click)="showModalInfo(activity)" (ionDrag)="itemDragged(iis)">
<p>{{iis.class}}</p>

But digging in the event class you can get the class like this
itemDragged(event){
console.log(event._elementRef.nativeElement.className);
}

Would you use a ViewChild, and get the nativeElement?
In the component API, note that the key is how you will access it in your code, the value passed to ViewChild is the "#" id you gave the component (this is ES6, in TS you'd use the ViewChild annotation):
...
queries { 'myElement' : new ViewChild ( 'myelement' ) }
...
In the markup:
<div #myelement></div>
In your component function (a handler, wherever you need to grab it), the nativeElement property gives you a reference to the HTML element, so you can set innerHTML, add a handler, or whatever else you need to do. There's of course other ways to do this by binding to properties (e.g. you can bind to (click) or [innerHTML]):
...
this.myElement.nativeElement... // etc.
...
Alternatively, if you wanted to use a single handler for multiple elements (say, a bunch of different clickable divs) you could use event.target to do the same thing. The problem with that is, because giving IDs is considered "bad" these days, you have to have an alternative way of IDing which DIV got clicked. You can check the label (innerHTML), you can give it a dummy style and check for that, etc.

Related

Angular assing attribute to all child elements?

I have a custom component in angular that i re-use everywere in my app. This is a button component and i call it like this where i want to use it: <app-delete-btn></app-delete-btn>
I want to set the attribute tabindex="1" to my component but it does not work.
This attribute gives a TAB order to specific html elements.
Upon inspecting this strange behaviour, and as of my understanding, tabindex works but you have to specify it for the parent and ALL the child components
So i did this and it worked:
Upon declaring my custom component in my html <app-delete-btn tabindex="1"></app-delete-btn> i gave him the tabindex
and then i had to add it in the app-delete-btn.ts button inside the component <button tabindex="1">Delete</button>
The problem is that i may re-use that button therefore i can't add the tabindex from within the component itself otherwise is going to apply everywhere i use it.
Finally my question is:
Is there a way when calling <app-delete-btn></app-delete-btn> to assing a tabindex property to all of it's childrens (and by childrens i mean the button delcared in the html of the component)?
Add this to your button :
#HostBinding('attr.tab-index')
tabIndex = 1;
This should do the exact same thing as this
<app-delete-btn tabindex="1"></app-delete-btn>
But automatically

Getting The Source Element From Click Event Handler In Angular

I am still new to Angular and I'm struggling to get the DOM Element of an Angular Click Listener.
What I have is the following component HTML:
<div *ngFor="let menuItem of menu; index as itemId" class="menuItem">
<div class="menuItem__top" (click)="itemClicked($event, !!menuItem.submenu)">
<!-- Additional divs inside... -->
</div>
</div>
I would like to toggle a class of "menuItem__top" when it is clicked. My approach was to use a click event listener but I can't get the source Element to apply the class on.
itemClicked(event, hasSubmenu){
console.log(this) //is the component
let target = event.target || event.srcElement || event.currentTarget;
if(hasSubmenu){
console.log(target);
}
}
It could be done by getting the target of the $event but this way I would need to check the target and move with closest(".menuItem__top") up to the correct source element.
Is there an easy way in Angular to pass the source element of the click listener to the click function or a way to get it inside the click function?
In vanilla JS it would be as easy as using "this" inside the click function, but in Angular this is bind to the component. (In this case, it would be ok to loose the binding to the component if this is the only way.)
I thought about two ways:
Assigning a dynamic reference containing some string and the itemId, passing the itemId and retrieving the reference object based on the itemId in the listener.
Using a #HostListener to listen on every "menuItem__top" click and toggling the class every time.
What do you think is the best way? I feel like I am missing something simple here.
Go the other way around. People are used to jQuery and the way it works (selecting elements already present in the DOM, then adding them a class). So in Angular, they try to do the same thing and grab the element that was clicked, to apply it a class. Angular (and React and others) work the other way around. They construct the DOM from data. If you want to modify an element, start with modifying the data it was generated from.
This <div class="menuItem__top"> that you click on is constructed from let menuItem. All you have to do is add a property, say "isClicked" to menuItem.
<div *ngFor="let menuItem of menu; index as itemId" class="menuItem">
<div class="menuItem__top"
[class.isClicked]="menuItem.isClicked"
(click)="menuItem.isClicked = true">
<!-- Additional divs inside... -->
</div>
</div>

Angular DOM elements are not showing

Hi I am using an UI Library (forced to, company issue..) which provides an Angular component, which renders a form.
Now I want to disable all of the input fields an buttons inside this form. But the component of the library doesn't provide me the possibility to pass a parameter to change the status to read only.
Now I have no other option to do dirty DOM hacking. However it doesn't seem to work.
Here is my HTML of my own component, where I render the Library Component:
<component-of-the-library #formComponent></component-of-the-library>
Now inside my own components class I reference it:
#ViewChild('formComponent', {read: ElementRef}) formComponent: ElementRef;
However when I use the nativeElement feature and the querySelectorAll() function I don't see the button elements:
ngAfterViewInit() {
console.log(this.formComponent.nativeElement);
console.log(this.formComponent.nativeElement.querySelectorAll('button'))
}
The first line outputs the DOM of the library component. There I also see the buttons.
However the second line just returns an empty NodeList.
Am I missing something?
Instead of doing all these, come up with a div overlay and with the size of your form and make show or hide it based on your needs.
It will be easier than disabling each form inputs and buttons. Also the overlay is not the component but your div.
I able to read the DOM Nodes present in the child component from the parent Component using ViewChild() https://stackblitz.com/edit/angular-edmyur?file=src%2Fapp%2Fapp.component.ts
EDIT: I see another problem. AfterViewChecked gets called multiple times...
I found the answer myself. The problem is the LifeCycleHook. AfterViewInit works for your own component, but it doesn't wait for the child components to finish rendering.
When I use AfterViewChecked it works!
However I am still puzzled, that logging the nativeElement has always given me the correct DOM, even though it's still not rendered.

How to style the nested firstElementChild in native Element Angular

I have this following Structure where the there are nested child components in Parent Component and i need to lay the focus on the Child component div programmatically.
I have reproduces this stackblitz for the above problem.
If you see the ts file, I have done the following
ngAfterViewInit(){
console.log(this.test);
this.test.toArray()[1].nativeElement.focus();
this.test.toArray()[1].nativeElement.firstElementChild.nativeElement.focus(); //this dosent work
}
The console.log returns me a query list of divs (in my original case a list of components) and in that I have a firstElementChild a (component) whose firstChildElement is a div I need to style and add focus on. But I am unable to do so as if you check the stacktrace it returns Cannot read property 'focus' of undefined.
In simple works the Structure:
ParentComponent -> viewChild gets me Query List of Child -> the array element has components -> each component has a firstElementChild -> property that has a div that I need to put focus on
UPDATE
Thanks all for your feedback and help really appreciated but now the thing is
It works but only if i give tab index for all the nested divs i was hoping that it trickles down the child the tab index. this is the problem. Any work around to this problem as this way i need to modify the template fro all my nested components in the broader sense
Try to change
this.test.toArray()[1].nativeElement.firstElementChild.nativeElement.focus(); //this dosent work
to
this.test.toArray()[1].nativeElement.firstElementChild.focus(); //this should work :-)
nativeElement.firstElementChild is NOT an ElementRef but already an HTMLElement => it doesn't have a property nativeElement.
Alternatively, children property of the HTML Element will also return a HTMLElementCollection as below,
this.test.toArray()[1].nativeElement.children[0].focus();
Updated Stackblitz
Updated template
<div>
<p> Welcome to the world of {{testHtml}} </p>
</div>
<div *ngFor = "let i of numbers; let ii = index" [attr.tabIndex] = "ii==00 ? 0 : null" #test>
<div>{{i}}
<div>
MY test
</div>
</div>
</div>
updated .ts file
ngAfterViewInit(){
this.test.toArray()[0].nativeElement.focus();
}
Note: You were using same tabindex for all the elements. You need to define tabindex for a selected one that you want to focus initally.

What is this.$() in Ember or JQuery

I saw example code on https://github.com/lukemelia/jquery-ui-ember. Can some one tell me what is this.$()
you can see this on jquery-ui-ember-master\jquery-ui-ember-master\js\app.js
this.$() is a call of the $-method of your current objectscope.
this refers to your current object.
$ is a function of this.
() will call the function $ of this.
When you create a Component, in its code this.$() gives you a jQuery object reference, set to the element that was inserted into the dom by that Component (its outer tag, usually a div unless you told it otherwise). You can then use for example this.$('.myclass') to find the element with the class myclass within the section of HTML that is handled by that Component without having to specify an id attribute to find the correct set of elements.
This probably also applies to the Views, but you should be using a Component instead whenever possible.
As Leeft said this.$() will give you the reference to the jQuery object, but typically you should only want to get the reference to the jQuery object in didInsertElement where the component has been inserted into the DOM and you can do jQuery-UI stuff on the element.

Categories

Resources