angle2 manuell Klickereignis auf ein bestimmtes Element auslösen

81

Ich versuche, das Klickereignis (oder ein anderes Ereignis) programmgesteuert auf ein Element auszulösen. Mit anderen Worten, ich möchte die ähnlichen Funktionen kennen, die die Methode jQuery .trigger () in angle2 bietet.

Gibt es eine eingebaute Methode, um dies zu tun? ..... wenn nicht, bitte vorschlagen, wie ich das machen kann

Betrachten Sie das folgende Codefragment

<form [ngFormModel]="imgUploadFrm"
          (ngSubmit)="onSubmit(imgUploadFrm)">
        <br>
        <div class="input-field">
            <input type="file" id="imgFile" (click)="onChange($event)" >
        </div>
        <button id="btnAdd" type="submit" (click)="showImageBrowseDlg()" )>Add Picture</button>
 </form>

Wenn der Benutzer auf btnAdd klickt , sollte das Klickereignis auf imgFile ausgelöst werden

Jorin
quelle
Sie müssen nur imgFile.click()statt, showImageBrowseDlg()wenn Sie der folgenden Antwort von @ akshay-khale stackoverflow.com/a/41675017/344029 (nach dem Hinzufügen der Variablen <input #imgFile)
folgen

Antworten:

182

Angular4

Anstatt

    this.renderer.invokeElementMethod(
        this.fileInput.nativeElement, 'dispatchEvent', [event]);

verwenden

    this.fileInput.nativeElement.dispatchEvent(event);

weil invokeElementMethodnicht mehr Teil des Renderers sein wird.

Angular2

Verwenden Sie ViewChild mit einer Vorlagenvariablen, um einen Verweis auf die Dateieingabe abzurufen , und rufen Sie dann mit dem Renderer auf, dispatchEventum das Ereignis auszulösen :

import { Component, Renderer, ElementRef, ViewChild } from '@angular/core';
@Component({
  ...
  template: `
...
<input #fileInput type="file" id="imgFile" (click)="onChange($event)" >
...`
})
class MyComponent {
  @ViewChild('fileInput') fileInput:ElementRef;

  constructor(private renderer:Renderer) {}

  showImageBrowseDlg() {
    // from http://stackoverflow.com/a/32010791/217408
    let event = new MouseEvent('click', {bubbles: true});
    this.renderer.invokeElementMethod(
        this.fileInput.nativeElement, 'dispatchEvent', [event]);
  }
}

Aktualisieren

Da der direkte DOM-Zugriff vom Angular-Team nicht mehr entmutigt wird, kann auch dieser einfachere Code verwendet werden

this.fileInput.nativeElement.click()

Siehe auch https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent

Günter Zöchbauer
quelle
10
this.fileInput.nativeElement.click()funktioniert anscheinend auch.
lbrahim
3
@lbrahim das ist richtig. Zu dieser Zeit war es ein starker Vorschlag, den Zugriff auf Eigenschaften oder Methoden zu vermeiden nativeElementund Rendererstattdessen zu verwenden. Ich denke, dies hat sich in letzter Zeit ziemlich geändert und der direkte DOM-Zugriff ist jetzt in Ordnung, aber es funktioniert nicht mit serverseitigem Rendering und WebWorkern.
Günter Zöchbauer
1
@AralRoca dann verwenden @ViewChildren('fileInput') QueryList<ElementRef>;Siehe auch stackoverflow.com/questions/32693061/…
Günter Zöchbauer
1
Ich bin mir da nicht ganz sicher und habe keine offiziellen Dokumente gesehen, die es erwähnen, aber soweit ich mich erinnere, wurde es in einigen GitHub-Ausgaben erwähnt. Ich denke auch daran, dass einige Dokumentbeispiele aktualisiert wurden, um den Renderer zu entfernen und den direkten DOM-Zugriff zu verwenden. Ich hatte den Eindruck, wenn Sie nicht beabsichtigen, serverseitiges Rendering oder Web-Worker zu verwenden, dann ist dies nur eine umständliche Einschränkung, und viele Entwickler kümmern sich nicht darum, und auf diese Weise haben sie es entfernt, dies zu einem zu machen starke Regel.
Günter Zöchbauer
1
@ ManuChadha warum überhaupt jquery verwenden? Dies kann zu Problemen führen, wenn Angular und jquery der Meinung sind, dass beide die volle Kontrolle über das FOM haben. jquery ist in letzter Zeit viel weniger relevant geworden, da die Unterschiede zwischen den Browsern viel geringer sind und die Unterstützung für alte Browser von den meisten vollständig eingestellt wurde.
Günter Zöchbauer
27

Ich wollte auch eine ähnliche Funktionalität , wo ich eine haben Datei - Input Control mit display:noneund ein Button - Steuerelement , wo ich Trigger wollte Click - Ereignis von Datei - Input Control , wenn ich auf den Button klicken, unten ist der Code zu tun,

<input type="button" (click)="fileInput.click()" class="btn btn-primary" value="Add From File">
<input type="file" style="display:none;" #fileInput/>

so einfach und das funktioniert einwandfrei ...

Akshay Khale
quelle
1
Ich habe genau dies verwendet, um auf eine Schaltfläche zu klicken, nachdem ich die Eingabetaste in einem Textfeld <input #name type="text" (keyup.enter)="addBtn.click()"> <button #addBtn (click)="add(name.value)" type="button">Add</button>
gedrückt habe
4

Das hat bei mir funktioniert:

<button #loginButton ...

und im Controller:

@ViewChild('loginButton') loginButton;
...
this.loginButton.getNativeElement().click();
Marco C.
quelle
Danke Kumpel. Mit ionic3 hat es wie ein Zauber funktioniert. :)
DwlRathod
Dies funktioniert nicht bei Angular 7+
Davejoem
2

Die Antwort von Günter Zöchbauer ist die richtige. Fügen Sie einfach die folgende Zeile hinzu:

showImageBrowseDlg() {
    // from http://stackoverflow.com/a/32010791/217408
    let event = new MouseEvent('click', {bubbles: true});
    event.stopPropagation();
    this.renderer.invokeElementMethod(
        this.fileInput.nativeElement, 'dispatchEvent', [event]);
  }

In meinem Fall würde ich den Fehler "Abgefangener RangeError: Maximale Aufrufstapelgröße überschritten" erhalten, wenn nicht. (Ich habe eine Div-Karte, die beim Klicken ausgelöst wird, und die Eingabedatei darin)

reneval
quelle
1
Sie können auch den Schlüssel "Bubbles" auf "false" setzen, um zu verhindern, dass das Ereignis den Dom-Baum sprudelt
ChicoDelaBarrio
2

Wenn Sie imitieren möchten, klicken Sie wie folgt auf das DOM-Element:

<a (click)="showLogin($event)">login</a>

und so etwas auf der Seite haben:

<li ngbDropdown>
    <a ngbDropdownToggle id="login-menu">
        ...
    </a>
 </li>

Ihre Funktion in component.tssollte wie folgt sein:

showLogin(event) {
   event.stopPropagation();
   document.getElementById('login-menu').click();
}
Rammgarot
quelle
0

Um den nativen Verweis auf so etwas wie ein zu erhalten ion-input, verwenden Sie dies

@ViewChild('fileInput', { read: ElementRef }) fileInput: ElementRef;

und dann

this.fileInput.nativeElement.querySelector('input').click()
Davejoem
quelle