19

I have a hidden input to control the changes made by jQuery, which includes an event of angular2 change, like this

<input id='input1' hidden (change)='onChange($event)'>

Then in my case, I have to use jQuery to change value of this input, then trigger change event:

$('#input1').val('somevalue').trigger('change');

This change event that I triggered via jQuery only works with jQuery, but not Angular2:

//This is working
$('#input').change(function(){
  console.log('Change made');
})

In angular2 component:

//This is not working
onChange(): void{
  console.log('Change made');
}

How can I work around in this situation?

2 Answers 2

19

You could assign a template reference variable to the <input>, like #hiddenInput1, get a hold of its native element (via @ViewChild) inside the component class and then use jQuery itself to listen to the change event.

Demo plunker here.

import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
  <h1>My First Angular 2 App</h1>
  <hr>
  <input id='input1' hidden #hiddenInput1>
  `
})
export class AppComponent implements AfterViewInit  {

  @ViewChild('hiddenInput1') hiddenInput1:ElementRef;

  ngAfterViewInit() {
    $(this.hiddenInput1.nativeElement).on('change', (e) => {
      console.log('Change made -- ngAfterViewInit');
      this.onChange(e);
    });
  }

  onChange(): void{
    console.log('Change made -- onChange');
  }

}
Sign up to request clarification or add additional context in comments.

2 Comments

I've been searching for this solution for like 2 days. Thank you very much.
Good job! You saved my day bro.
18

Angular2 change event is added via native addEventListener.

You cannot trigger a native event with jQuery's .trigger('change'). So you will need to create a native event and dispatch it:

 const customEvent = document.createEvent('Event');  
 customEvent.initEvent('change', true, true);
 $('#input1')[0].dispatchEvent(customEvent);

This way angular2 will fire onChange handler.

Here is a demo plunker

As @Cristal Embalagens mentioned in comments you need to use input event for angular2 because DefaultValueAccessor is subscribing on this event:

@Directive({
  selector:
      'input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]',
  host: {'(input)': 'onChange($event.target.value)', '(blur)': 'onTouched()'},
  providers: [DEFAULT_VALUE_ACCESSOR]
})
export class DefaultValueAccessor implements ControlValueAccessor {

Some Example

5 Comments

I'd say your solution works but @acdcjunior's answer seems to be the cleaner solution for me. Thanks.
For input fields use initEvent('input', true, true) to trigger the change event to angular2.
Thank you @CristalEmbalagens . Works! I wasted 5 hours because I didn't read your comment before :)
@yurzui perfect! Your answer here was the key to my solving the problem of making Bootstrap events visible/observable from within Angular components.
@CristalEmbalagens Lifesaver! thanks for this awesome information!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.