0

I have an input component, an output component, and a processing service. I would like the user to input a string, and for the processing service to output a processed message to the output component. The trouble I am having is getting the processed message from the processing service. Here is what I have so far:

<input class="input" type ="text"[(ngModel)]="text" (keyup.enter)="process(text)">
export class InputComponent {
    text: String;
    constructor(private processService: ProcessService){}
process(text){
        this.processService.process(text);
}
}
export class ProcessService {
processedMsg: string;
    process(msg) {
    this.processedMsg = "a message thats processed";
    }
    getMessage() {
    return this.processedMsg;
    }
    }
        export class OutputComponent {
    output: string;
            constructor(private processService: ProcessService){}
            getOutput() {
                this.output = this.processService.getMessage();
            }

How can I make it so that when the user presses enter, the input is processed, and is given to the output? Thanks.

yoog
  • 13
  • 2

1 Answers1

0

There are a couple ways to achieve the effect your going for. This first way is the simplest to grasp I think and it follows what you have so far pretty closely. All this does is directly tell the template to display the value that the service last processed, this is not recommended.

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

@Injectable()
class ProcessService {
  processedMsg: string = "";
  process(msg) {
    this.processedMsg = "Processed: \""+msg+"\"";
  }
}

@Component({
  selector: 'output',
  template: '<span>{{processService.processedMsg}}</span>'
})
class OutputComponent {
  constructor(public processService: ProcessService){}
}

@Component({
  selector: 'my-app',
  directives: [OutputComponent],
  providers: [ProcessService],
  template: `
    <input class="input" type ="text" [(ngModel)]="text" (keyup.enter)="process(text)"><br>
    <output></output>
  `
})
export class AppComponent {
  text:string;
  constructor(private processService: ProcessService){}
  process(text){
    this.processService.process(text);
  }
}

We could also do this using Observables, see this answer for the source: Delegation: EventEmitter or Observable in Angular2

import { Component, Injectable, OnInit, OnDestroy } from '@angular/core';

import {BehaviorSubject} from "rxjs/BehaviorSubject";
import {Subscription} from 'rxjs/Subscription';

@Injectable()
class ProcessService {
  private _processedMsgSrc: BehaviourSubject<string> = new BehaviorSubject<string>("");
  processedMsg = this._processedMsgSrc.asObservable();
  process(msg) {
    this._processedMsgSrc.next("Processed: \""+msg+"\"");
  }
}

@Component({
  selector: 'output',
  template: '<span>{{output}}</span>'
})
class OutputComponent implements OnInit, OnDestroy {
  output:string;
  private _subscription:Subscription;
  constructor(public processService: ProcessService){}
  ngOnInit() {
    this.subscription = this.processService.processedMsg.subscribe(
      msg => this.output = msg
    );
  }
  ngOnDestroy() {
    // stop the subscription when the component is destroyed
    this.subscription.unsubscribe();
  }
}

@Component({
  selector: 'my-app',
  directives: [OutputComponent],
  providers: [ProcessService],
  template: `
    <input class="input" type ="text" [(ngModel)]="text" (keyup.enter)="process(text)">
    <br>
    <output></output>
  `
})
export class AppComponent {
  text:string;
  constructor(private processService: ProcessService){}
  process(text){
    this.processService.process(text);
  }
}

The second way would probably be better as it completely separates the two components, allowing you to change how the Process Service works completely without changing any other code.

Community
  • 1
  • 1
Tiedye
  • 544
  • 1
  • 4
  • 7