Search code examples
angularangularjs-scopeionic2angularjs-serviceionic-tabs

How to share variables across components in Ionic 2?


In Ionic 1 (With Angular 1), I can create a $scope.abc on the ngApp layer and other ngControllers can inherit $scope.abc with ngModel, so that when a text area in one controller changes, the others will change accordingly via ngModel.

How may I achieve "synchronized text area" with Ionic 2 (and Angular 2)?

Here are some of my attempts:

  1. Injecting MyApp in the constructor of the components: the [(ngModel)]="myApp.abc" will result in a undefined error in console of failing to resolve context.myApp.abc...
  2. Creating a Service with a setter. Use [(ngChange)] to call the setter and use getter in the constructor of another component: the text area doesn't change after the component is instantiated. Using ViewOnInit instead of Constructor doesn't help either. Is there an event handler for "component is shown on screen"?

Solution

  • Create a service and add this service to the shared parent component (or if there isn't one, add it to app component's) list of providers. Make sure to import the service in each component that needs to use the service. Then inject the service in constructor of each component that needs it.

    Plunkr example: https://plnkr.co/l3BlNdjQfzPIIGPSXp9n?p=preview

    // >>>home.ts
    import { Component } from "@angular/core";
    import { Component1 } from "./component1.ts";
    import { Component2 } from "./component2.ts";
    
    import { YearService } from "./year.service.ts"
    @Component({
      templateUrl:"home.html",
      directives: [Component1, Component2],
      providers: [YearService]
    })
    export class HomePage {
    
      constructor() {   }
    
    }
    
    // >>>home.html
    <ion-header>
      <ion-navbar primary>
        <ion-title>
          Ionic 2
        </ion-title>
      </ion-navbar>
    </ion-header>
    
    <ion-content>
      <comp-one></comp-one>
      <comp-two></comp-two>
    </ion-content>
    
    // >>>component1.ts
    import { Component } from "@angular/core";
    import { YearService } from "./year.service.ts";
    
    @Component({
      templateUrl: "./component1.html",
      selector: "comp-one"
    })
    export class Component1 {
      constructor(yearSvc: YearService) {   
        this.year = yearSvc.getYear();
      }
    }
    
    // >>>compnent1.html
    <p> Year from component 1 using a shared service: <strong>{{year}}</strong></p>
    
    // >>>component2.ts
    import { Component } from "@angular/core";
    import { YearService } from "./year.service.ts";
    
    @Component({
      templateUrl: "./component2.html",
      selector: "comp-two",
    })
    export class Component2 {
      constructor(yrSvc: YearService) {
        this.year = yrSvc.getYear();
      }
    }
    
    // >>> component2.html
    <p> Year from component 2 using a shared service: <strong>{{year}}</strong></p>
    
    // >>> year.service.ts
    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class YearService {
      getYear() {
        return new Date().getFullYear();
      }
    }