angular2 вручну запускає подію клацання на певному елементі


82

Я намагаюся запускати подію клацання (або будь-яку іншу подію) на елементі програмно, Іншими словами, я хочу знати подібні функції, які пропонує метод jQuery .trigger () у angular2.

Чи є якийсь вбудований метод для цього? ..... якщо ні, підкажіть, як я можу це зробити

Розглянемо наступний фрагмент коду

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

Тут, коли користувач натискає btnAdd, він повинен запускати подію клацання на imgFile


Вам потрібно тільки imgFile.click()замість того , showImageBrowseDlg()якщо ви будете слідувати нижче відповідь на @ Акшай-khale stackoverflow.com/a/41675017/344029 (після додавання змінної <input #imgFile)
DJDaveMark

Відповіді:


184

Кутова4

Замість

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

використання

    this.fileInput.nativeElement.dispatchEvent(event);

тому що invokeElementMethodбільше не буде частиною візуалізатора.

Кутова2

Використовуйте ViewChild із змінною шаблону, щоб отримати посилання на вхідний файл, а потім використовуйте Renderer для виклику dispatchEventдля запуску події:

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

Оновлення

Оскільки прямий доступ до DOM більше не перешкоджає команда Angular, цей простіший код також може бути використаний

this.fileInput.nativeElement.click()

Див. Також https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent


10
this.fileInput.nativeElement.click()також працює, здається.
lbrahim

3
@lbrahim це правильно. Тоді настійно рекомендували уникати доступу до властивостей або методів nativeElementта використання Rendererнатомість. Я думаю, це нещодавно змінилося нещодавно, і прямий доступ до DOM зараз прекрасний, але він не буде працювати з візуалізацією на стороні сервера та WebWorkers.
Günter Zöchbauer

1
@AralRoca потім використовувати @ViewChildren('fileInput') QueryList<ElementRef>;Дивіться також stackoverflow.com/questions/32693061 / ...
Гюнтер Zöchbauer

1
Я не зовсім впевнений у цьому, і я не бачив офіційних документів, в яких про це згадується, але, наскільки я пам’ятаю, це згадувалося в деяких випусках GitHub. Я також пам’ятаю, що деякі приклади документів були оновлені, щоб видалити візуалізатор та використовувати прямий доступ до DOM. У мене склалося враження, якщо ви не збираєтеся використовувати рендеринг на стороні сервера або веб-співробітників, тоді це просто громіздке обмеження, і досить багато розробників не хвилює це, і що таким чином вони усунули, роблячи це сильне правило.
Гюнтер Цохбауер,

1
@ManuChadha, навіщо взагалі використовувати jquery? Це може призвести до проблем, коли Angular та jquery вважають, що вони обидва повністю контролюють FOM. Останнім часом jquery стає набагато менш актуальним, оскільки відмінності між браузерами значно менші, а підтримка старих браузерів більшістю повністю відмовлена.
Günter Zöchbauer

27

Я також хотів схожу функціональність , де у мене є вхідний контроль файлів з display:noneі управління Button , де я хотів , щоб тригер події натискання вхідного файлу контролю , коли я натискаю на кнопку, нижче код , щоб зробити це

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

так просто, і це працює бездоганно ...


1
Я використав саме це, щоб натиснути кнопку після натискання клавіші Enter у текстовому полі:<input #name type="text" (keyup.enter)="addBtn.click()"> <button #addBtn (click)="add(name.value)" type="button">Add</button>
DJDaveMark

4

Це спрацювало для мене:

<button #loginButton ...

і всередині контролера:

@ViewChild('loginButton') loginButton;
...
this.loginButton.getNativeElement().click();

Дякую друже. це працювало як шарм з ionic3. :)
DwlRathod

2

Відповідь Гюнтера Цехбауера правильна. Просто подумайте про додавання наступного рядка:

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

У моєму випадку я отримаю помилку "зловив RangeError: перевищено максимальний розмір стека викликів", якщо ні. (У мене є карта div, яка запускається після клацання, і вхідний файл всередині)


1
Ви також можете встановити для клавіші "бульбашки" значення "false", що запобігає появі бульбашок над деревом
купола

2

Якщо ви хочете імітувати, натисніть на елемент DOM так:

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

і мати щось подібне на сторінці:

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

ваша функція в component.tsповинна бути такою:

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

1

Щоб отримати власне посилання на щось на зразок an ion-input, використовуйте це

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

і потім

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

Дуже дякую! Я намагався змусити це працювати в іонічному. Привітання
fromage9747

Ласкаво просимо
davejoem
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.