Vishu
Vishu

Reputation: 1125

How to pass variable value from one component to another in angular 2

app.component.ts

@Component({
  moduleId: module.id,
  selector: 'mx-itool-clock',
  template: `<leftpanel></leftpanel><workmat></workmat>`,
  directives: [ClockWorkmat,ClockLeftPanel]
})

export class AppComponent{
}

leftpanel.component.ts

@Component({
  moduleId: module.id,
  selector: 'clock-leftpanel',
  template: `<div class="show-time">{{time}}</div>',
})
export class ClockLeftPanel {
    time:number=10;
}

workmat.component.ts

@Component({
    moduleId: module.id,
    selector: 'clock-workmat',
    template: '<div>{{time}}</div>',
})
export class ClockWorkmat {
  time:number;
}

i want to to take value of time from leftpanel.component.ts and assign to time in workmat.ts

can anyone please tell how to achieve it in simple way using angular 2 rc4.

Upvotes: 4

Views: 36205

Answers (5)

William Hou
William Hou

Reputation: 1771

So far I know two ways to do this. One way is with a custom service, which is not simple, although it's a better way because services are generally used when you need to reuse data or logic across multiple components.

The Simple Way is through an "@Input() time: number" variable.

Step 1: First create a method to get "time" in your leftpanel.component.ts file:

      export class ClockLeftPanel {
          time:number=10;

          getTime() : number {
              return: this.time;
          }
      }       

Step 2: Then, make the "template" in your leftpanel.component.ts like the following:

      template: `
                <div class="show-time">{{time}}</div>
                <clock-workmat [time]="getTime()"></clock-workmat>
                `

which will nest the workmat.component with the leftpanel.component, allowing you to pass value from leftpanel.component to workmat.component. Remember to use backticks (``), not quotation marks (" " or ' ') because there is more than one line.

Step 3: Next, in your workmat.component, you need to receive the value from the leftpanel.component with the @Input() decorator. In your workmat.component.ts, do the following:

      import {Input} from '@angular/core';
      ...
      export class ClockWorkmat {
          @Input() time: number;
      }

The above-given method can only go as far as where you are showing in your question.

If you want to use the value you got from leftpanel.component.ts Many Times Across Multiple Components, you need to use a custom service, which won't be so simple, but not too bad though. Actually, a service is very satisfying in many occasions.

Upvotes: 1

Yonatan Doron
Yonatan Doron

Reputation: 56

If two children components of the parent "app" component need access to such a variable, I would originally aspire to keep all logic relating to this variable under the parent component, hence 'app' in your case.

If for some reason it conflicts with the design of your app and you most have this variable under leftpanel component then ther are various solutions to this problem.

The easiest solution I see is to implement NgRedux and set it up in your project, by doing so you could dispatch an update to a certain state that holds record of this variable and gives easy access to it's value anywhere around your up easily bu subscribing to that certain state.

If you aren't famliar with NgRedux and want something less efficient but immediate you can do it the Angular way by importing these: Output, EventEmitter in your leftpanel comp, and emitting an event wherever neccesary(ngOnInit / on activation of a function, for example) and importing Input in your app component. Naturally the parent will listen to this event and upon triggering will activate a function that for now will just update a private variable in 'app' comp, like so:

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
    moduleId: module.id,
    selector: 'letf-panel',
    template: ` 
               <div>Left Panel Content</div>
    `
})
export class LeftPanelComponent {
    @Output() timeEvent = new EventEmitter();

    constructor() {}
}

And then under NgOnInit (Inside the LeftPanelComponent class) for example I emit the event with the time variable:

ngOnInit() {
   this.timeEvent.emit(time)
}

You Input the event like so:

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

@Component({
    moduleId: module.id,
    selector: 'app',
    template: '<div (timeEvent)="getTime()"></div>',
})
export class AppComponent{

  @Input() time:number;
  private timeInApp;

  getTime(timeFromLeftPanel) {
      this.timeInApp = timeFromLeftPanel;
  }
}

Once you have the variable in app comp you could Bind it to the workmat component like so:

[time]="time"

And in the template:

template: `<leftpanel #src></leftpanel><workmat [time]="time"></workmat>`

Let me know if this helps you with the problem

Upvotes: 4

ultimamanu
ultimamanu

Reputation: 13

I'm not completely sure if this will work fine in Angular 2 rc4, but at least it should work with the latest release versions. I think you could use template variables in your parent component to achieve what you want (eg. you assign the template name "src" [for instance] to your leftpanel, and then you set the time value with it in your workmat component as below):

  • in app.component.ts:
@Component({
  moduleId: module.id,
  selector: 'mx-itool-clock',
  template: `<leftpanel #src></leftpanel><workmat [time]="src.time"></workmat>`,
  directives: [ClockWorkmat,ClockLeftPanel]
})
  • workmat.component.ts
import { Input } from '@angular/core';

@Component({
    moduleId: module.id,
    selector: 'clock-workmat',
    template: '<div>{{time}}</div>',
})
export class ClockWorkmat {
  @Input() time:number;
}

And this should do the trick for a one shot assignment. Now if you want to continuously retrieve the time value from the leftpanel and assign it to your workmat instance, then you would have to introduce an EventEmitter in your LeftPanel component: see this page for more details

Upvotes: 0

Nikolay Babanov
Nikolay Babanov

Reputation: 421

You need to create a shared service and inject it in the components you want to share data. For the service to have a shared instance, it needs to be listed in the providers array of the module, your components are part of or a top level module.

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { 
    AppComponent,
    ClockLeftPanel,
    ClockWorkmat
} from './path';

@NgModule({
    imports: [...],
    exports: [...],
    providers: [
        YourService
    ],
    declarations: [
        ClockLeftPanel,
        ClockWorkmat,
        AppComponent
    ]
})
export class YourModule { }

Upvotes: 0

ranakrunal9
ranakrunal9

Reputation: 13558

Usage of directives inside @Component is deprecated now so it will give you error inside AppComponent if you are using latest angular version.

For your component communication i will advice you to use component communicate via a service in which you need to create one shared service. you can also check my answer of parent-child or sibling component communication or gist.

Upvotes: 2

Related Questions