global function in Ionic 2 / Angular 2
Asked Answered
A

4

9

How can I setup a global function that can be accessed throughout all views?

In app.component.ts I added a simple method

  openShare() {console.log("button clicked")} 

and then in my nav I have

  <button ion-button right (click)="openShare()">
  <ion-icon name="md-share"></ion-icon>
</button>

When I try to access this from any page I get the following.

self.context.openShare is not a function

It does however execute fine if I put it directly in the constructor (e.g this.openShare(); ), but when calling from any page using a (click) function it just doesn't work.

Is app.component.ts not global? I thought this is where I would place it, but maybe I am missing something.

Basically its a function for a simple button on the nav, I need it to be global though since its used on every page.

Any help would be appreciated, still figuring Ionic 2 out.

Artiste answered 2/4, 2017 at 3:19 Comment(4)
Try a custom directive.Oft
Any example code how I would do this?Artiste
angular.io/docs/ts/latest/guide/attribute-directives.htmlOft
@HarishKommuri - This might also work. If anyone has a simple example would be appreciated. I am more visual, not asking to write the code just a simple example on a click method.Artiste
O
11

You can use Directive.

Try as follows.

Put the following code in separate directive file. (social-sharing.directive.ts);

import { Directive, HostListener } from '@angular/core';

@Directive({
  selector: '[socialSharing]'
})
export class SocialSharing {

  constructor() { }

  @HostListener('click') onClick() {
    // Your click functionality
  }
}

Import it into app.module.ts and than add to declarations.

In HTML, just add attribute to any element which is the selector in your directive file.

<button ion-button right socialSharing>
 <ion-icon name="md-share"></ion-icon>
</button>

Additional Info:

Passing values from component to directive.

home.html

  <button ion-button right [socialSharing]="property">
    <ion-icon name="md-share"></ion-icon>
  </button>

home.component.ts

 export class HomePage {

   property: string = 'some url';
    constructor() {}
 }

social-sharing.directive.ts

Import Input along with others from @angular/core.

import { Directive, Input, HostListener } from '@angular/core';

@Directive({
   selector: '[socialSharing]'
})

export class SocialSharing {
  @Input('socialSharing') str: string;

  constructor() {}

  @HostListener('click') onClick() {
     console.log(this.str);
  }
};

  ngAfterInit() {
     console.log(this.str);
  };
}

Using Element in Directive:

social-sharing.directive.ts

Import ElementRef along with others from @angular/core

 import { Directive, ElementRef, HostListener } from '@angular/core';

 @Directive({
   selector: '[socialSharing]'
 })

 export class SocialSharing {

   // Add ElementRef to constructor

   constructor(el: ElementRef) {};

   ngOnInit() {
      let elRef = this.el.nativeElement;
      console.log(elRef.innerHTML);        
   };
 }
Oft answered 2/4, 2017 at 10:39 Comment(1)
- Hey thank you. This actually worked perfect. A lot of posts for people wanting to know how to do this. Hopefully they find your answer here. Thank you, much appreciated.Artiste
C
8

You can easily do that using Providers.When you need to use that functionality (or provider), you just need to inject it into your related component.That is it.

Method 1:

You can create a Provider using CLI.

> ionic g provider YourProvider

your-provider.ts

 import { Injectable } from '@angular/core';

    @Injectable()
    export class YourProvider {

      constructor() {
      }

       openShare() {console.log("button clicked")} 
    }

app.module.ts

import { YourProvider } from "../pages/path";

    @NgModule({
      declarations: [
        MyApp,
      ],
      imports: [
        IonicModule.forRoot(MyApp),
       ],
      bootstrap: [IonicApp],
      entryComponents: [
        MyApp,
        ],
      providers: [{ provide: ErrorHandler, useClass: IonicErrorHandler },YourProvider  ]
    })

    export class AppModule { }

your-view.ts

       import { YourProvider } from '../../providers/your-provider';

        export class YourViewPage{

          constructor(public yourProvider : YourProvider) {

          }

        openShare(){
           this.yourProvider.openShare(); 
        }

Method 2: Creat an abstract base class.

my-base-class.ts

export abstract class MyBaseClass {

  constructor() {
  }

  protected openShare():void {
    console.log("button clicked"); 
  }

}

my-view.ts

export class MyViewPage extends MyBaseClass {
  constructor()
  {
     super();
  }

       openShare(){
               super.openShare(); 
            }
  }
Confucian answered 2/4, 2017 at 3:27 Comment(3)
hmm.. yeah this is kind of how I set things up now, but for a simple function seems like too many imports over 20 pages. Is this the only way? This is for a button in the nav header so basically called on every page.Artiste
Thanks for the help. Interesting with the abstract class, will give this a try.Artiste
sure.hope you'll share the result with us :)Confucian
F
3

Just like @Sampath mentioned, one way would be to use a custom provider. But since you method is just a simple one, I think you can use Events instead. It'd be like this:

In your app.component.ts file, subscribe to the new event:

import { Events } from 'ionic-angular';

constructor(public events: Events, ...) {

  // ...

  events.subscribe('social:share', () => {

    // your code...
    console.log("button clicked");

  });

}

And then in any other page, just publish the event to execute that logic:

function anotherPageMethod() {
  this.events.publish('social:share');
}
Frill answered 2/4, 2017 at 4:28 Comment(1)
Thanks, this might work. Still though - I can't believe something so global as a nav bar, there is no simple way to declare common methods. So much for keeping it DRY. Was simple in Ionic 1. Oh well - Really appreciate the help. Thanks again.Artiste
B
0

For anyone coming across this, have a look at using shared module, that in turn includes a shared component

Create a custom component that you will use as your shared component by using the Ionic CLI as follows:

ionic g component components/nameofcomponent

Where nameofcomponent is the name you want to use for your shared component

See this article for example, on how to create a shared module to include your shared component

Bullbat answered 17/7, 2023 at 9:12 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Fellowman

© 2022 - 2025 — McMap. All rights reserved.