Angular2 How to get reference of HTML elements generated dynamically
Asked Answered
S

5

37

I have this inputs generated dynamically:

  <div *ngFor="let cell of column; let i = index;">
          <!-- Material design input-->
          <md-input id="my-input-{{i}}">
          </md-input>
  </div>

Please notice id=my-input-{{i}} I would like to get a reference to the DOM element based on this dynamic id. This input can be 3, 6 or more inputs so I need to access the id dynamically and get a hold to it.

Scrubber answered 10/11, 2016 at 18:55 Comment(11)
What are you trying to accomplish?Chesty
@Chesty I Need to get values of all inputs on press of a button, the problem is that they can vary in amount and their content, for example they can be 3 inputs or 6 inputs or 4 or 5... so I need some way to generate dynamic id and get their contents dynamicallyScrubber
is it enought if you can access to the dom ?Vanmeter
plnkr.co/edit/O1VCGMMLPqhaQAXyKzYp?p=previewChesty
@Vanmeter if I can acces their value and know their id it would be usefulScrubber
you could access to the dom with the ElementRef.naviteElement. Check this #32693561Vanmeter
@Vanmeter and once I get the DOM how to access element by id="blabla"Scrubber
with a selector 'elementRef.nativeElement.select("#blabla")'. maybe it is not the best solution, but i think could solve itVanmeter
@Chesty if you want to include answer Ill upvote and select your answer tjanksScrubber
@Vanmeter your answers helps if you want to include ill upvote thanksScrubber
answer posted, thanks!Vanmeter
S
50

The simplest answer is to rely on vanilla javascript

const el:Element = document.getElementById("myProgrammaticallyChosenIndex")

No other angular weird ceremony needed

Tested on angular 4+

Sunrise answered 1/10, 2017 at 20:0 Comment(7)
No sure why that ceremony comment made me laughDreamland
just going to comment on this that angular has the weird ceremony for a reason. It doesn't apply to all developers who are only ever going to be publishing to web but angular's long term purpose is to make a unified app development platform that can be used across devices. Using document functions like this makes that not possible since other platforms / targets might not implement document the same way.Scripture
Interesting, but we are so far away of a cross platform product... And flutter coming from Google seems to be their next very big cross thing. I suppose we will never get any angular cross platform.Sunrise
@DavidF., what about Ionic and NativeScript? Both tools allow us to build hybrid app that is based on AngularMarylynnmarylynne
Ionic is fine, I use it daily. Plus with the new Ionic 4 you use regular angular cli, Ionic 4 and Angular 7 are exactly the same. Native script I presume would not work.Sunrise
But how can we do it using the angular lifecycle hooks ?Baa
indeed it's better to use after ngAfterviewInitSunrise
L
12

Use ElementRef class from @angular/core to get the parent element and then create an HTMLElement to get its dynamic elements by class name.

Component:

declare var $: any; //intentional use of jQuery-not recommended though

@Component({
  selector: 'my-app',
  template: `
    <input type='button' (click)='addDiv()' value='Add New Div' />

    <input type='button' (click)='selectDiv()' value='Select' />
  `
})
export class App {
  constructor(private elRef: ElementRef) {
  }

  addDiv() {
    /*intentional use of jQuery for appending new div
     give a class to your dynamic elements*/

    $('my-app').append("<div class='foo'>Hello I'm Dynamic!</div>");
  }

  selectDiv() {
    //create a new HTMLElement from nativeElement
    var hElement: HTMLElement = this.elRef.nativeElement;

    //now you can simply get your elements with their class name
    var allDivs = hElement.getElementsByClassName('foo');

    //do something with selected elements
    console.log(allDivs);
  }
}

Working Plunker

Edit: I used jQuery only for quick demo purpose here. Otherwise, you should not use jQuery with Angular.

Lamonicalamont answered 23/12, 2016 at 18:32 Comment(4)
You should not include a code demo for something that you do not recommend doing, beside the fact that the question never mentioned using jQuery.Siegbahn
@wrldbt: "quick demo"Lamonicalamont
Using jQuery in a code sample for an entirely different framework is distracting and not ideal. One strong case for Angular is that it doesn't have to be tied directly into the web interface. Learning how to use the abstraction layers Angular has put in place to allow you to serve multiple different mediums is something we as developers should strive to teach others about.Bracknell
I have to agree with the downvoters. An answer including jQuery in an Angular app is not only counter-intuitive, it assumes familiarity with jQuery and also is a literal anti-pattern. The downvote is a technicality, but the technicalities are what keep stack overflow awesome.Bawdyhouse
S
1

If you have mulitple selectors you can use @ViewChildren. // Html

<div *ngFor="let cell of column; let i = index;">
          <!-- Material design input-->
          <md-input id="my-input-{{i}}" #inputBinding>
          </md-input>
  </div>

// TS File

@ViewChildren('inputBinding') inputBinding: QueryList<ComponentName>;

ngAfterViewInit(){
 console.log(this.inputBinding.toArray());
}
Suiter answered 9/4, 2021 at 17:44 Comment(0)
V
-1

You can access the DOM by the elementRef.

Inject it through your constructor by

constructor(myElement: ElementRef) { ... }

And access the DOM element by the nativeElement property

myElement.nativeElement.select("#blabla")
Vanmeter answered 10/11, 2016 at 19:51 Comment(2)
elementRef.nativeElement does not have a select method.Dreyer
should be myElement.nativeElement.select('#blabla')Wickedness
L
-1

There is a class called ElementRef class

It gives your permit direct access to the current component or directive hosting DOM.

You can use ElementRef.nativeElement to get a HTML element, then you can access to html element properties to make your modification by using jQuery or Renderer class provided by Angular 2.

Example with ElementRef and Renderer:

import { Directive, ElementRef, Input, Renderer } from '@angular/core';
@Directive({ selector: '[myHighlight]' })
export class HighlightDirective {
    constructor(el: ElementRef, renderer: Renderer) {
       renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'yellow');
    }
}
Livialivid answered 10/11, 2016 at 21:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.