Search code examples
angularweb-component

Create public method on angular component for outside of angular access


If I query an angular element in, for example, the DevTools console

$> $('app-foo').setSomething('yolo');

it doesn't work, telling me that setSomething does not exist.

I tried to create an angular component like this

@Component({
     selector: 'app-my-component',
     template: 'my component'
})
export class MyComponent {
    @Input()
    setSomething(input: string): void {
        // do magic
    }
}

DEMO

However, if I compile my component to a web component (using @angular/elements) it actually works. But in my current case I'm not going to create a web component and I have to deal with angular components. So the question is, how can I make a method available on the DOM instance? If there is an other way of doing this please let me know as well!

UPDATE: The reason I would like to this this is because I created a web component with @angular/elements called lib-foo. This component should receive an other component as follows

<lib-foo>
     <an-angular-component></an-angular-component>
</lib-foo>

The template from lib-foo is just <slot></slot> (shadowdom enabled).

From within lib-foo I would like to access an-angular-component, so I did

child = this.element.nativeElement.children[0]; // an-angular-component
contentChild.setSomething('yolo');

lib-foo should only get children which have a setSomething method. But whatever I do to create an-angular-component in my other angular project, these components never have that method


Solution

  • You are probably going to get a lot of responses telling you how what you are trying to do is a bad idea. It certainly isn't the best practice, and having to do something like that is a sign that you should reconsider your application's design and architecture.

    But if you really must, this is one way to do it:

    @Component({
      selector: 'app-foo',
      templateUrl: './foo.component.html',
      styleUrls: ['./foo.component.css']
    })
    export class FooComponent {
    
      constructor(elementRef: ElementRef) {
        // get the native element and set a function on it
        (elementRef.nativeElement as any).setSomething = this.setSomething
      }
    
      @Input()
      setSomething(input: string) {
         console.log('set something');
      }
    }

    You can then query the document for the element and call the function on it, i.e. $('app-foo').setSomething();

    If you are trying to access the child component's method from a parent component, you can use https://angular.io/api/core/ViewChildren to access them. If you want to use the methods from outside angular, then the snippet above will be what you are looking for.