0

Component A

I have a form with a button which should call a service class. The service returns an extracted JSON result.

compare() {
    this.getResults();
}

getResults() {
    this.resultService.getResults()
        .subscribe(
            results => this.results = results,
            error =>  this.errorMessage = <any>error);
}

Template of A:

<form (ngSubmit)="compare()" #compareForm="ngForm">
    <div class="col-md-5">
        <h1>Disk Forensics</h1>

        <div class="form-group">
            <label for="resourceA">Disk A</label>
            <select ngbDropDown class="form-control" id="resourceA" required [(ngModel)]="resourceA" name="resourceA">
                <option *ngFor="let r of disks" [value]="r.id">{{r.name}}</option>
            </select>
        </div>
        <div class="form-group">
            <label for="resourceB">Disk B</label>
            <select class="form-control" id="resourceB" required [(ngModel)]="resourceB" name="resourceB">
                <option *ngFor="let r of disks" [value]="r.id">{{r.name}}</option>
            </select>
        </div>

        <button type="button" (click)="compare()">Compare</button>

        <div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
    </div>

    <h4>Mode</h4>
    <div class="radio">
        <label>
            <input type="radio" name="diffmode" id="diffmode1" value="diffmode1" checked>
            different
        </label>
    </div>
    <div class="radio">
        <label>
            <input type="radio" name="diffmode" id="diffmode2" value="diffmode2">
            identical
        </label>
    </div>
    <div class="radio">
        <label>
            <input type="radio" name="diffmode" id="diffmode3" value="diffmode3">
            Left only
        </label>
    </div>
    <div class="radio">
        <label>
            <input type="radio" name="diffmode" id="diffmode4" value="diffmode4">
            Right only
        </label>
    </div>
</form>

Service Class

public getResults(): Observable<Result[]> {
    let body = JSON.stringify('{}');

    var options:RequestOptionsArgs = {
      body: "{}"
    }

    return this.results = this.http.get(this.url, options)
                    .map(this.extractData)
                    .catch(this.handleError);
  }

Component B

Is just to display the results from the service

result.component.html:

<div class="col-md-12">
    <h1>Results:</h1>
    <div>
        <p *ngFor="let r of results; let i=index">
            {{i + 1}}: {{r}}
        </p>
    </div>
    <div class="error" *ngIf="errorMessage">{{errorMessage}}</div>
</div>

result.component.ts:

import {Component, OnInit, Input} from '@angular/core';
import { Result } from "../models/result";
import {ResultService} from "../services/result.service";

@Component({
    selector: 'diff-result',
    templateUrl: './diff-result.component.html',
    styleUrls: ['./diff-result.component.css'],
    providers: [ResultService]
})
export class DiffResultComponent implements OnInit {


    errorMessage: string;

    constructor(private resultService: ResultService) { }

    ngOnInit() {
        this.getResults()
    }

    getResults() {
        this.resultService.getResults()
            .subscribe(
                results => this.results = results,
                error =>  this.errorMessage = <any>error);
    }
}

What I'd like is to trigger from the compare()-function that the service is being called and the result.html is updated with the results.

Since this is a sibling component, assuming I can't use the ViewChild-attributes.

Many thanks for your help

4
  • Actually I'd like to pass data to a property of another component. In the getResults() function of Component A instead of this.results I'd like to pass the results to the property of Component B. Commented Sep 22, 2016 at 11:01
  • Why component B isn't calling the service? Please show that template of Component A.. Commented Sep 22, 2016 at 11:09
  • @mxii, please find the updated template. Thanks Commented Sep 22, 2016 at 11:18
  • i've tried also: button type="button" (click)="b.getResults()">Compare</button> Marking the template like this: <diff-result #b></diff-result> But I get: inline template:17:30 caused by: Cannot read property 'getResults' of undefined Commented Sep 22, 2016 at 11:29

1 Answer 1

1

You can use a public Subject in your service.

Component A will trigger the comparison and Component B will consume the result.

Take a look at this plunker: https://plnkr.co/edit/5vny5d4rfudq06qrJAOR?p=preview

import {Component, NgModule, Injectable} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'

import {Subject} from 'rxjs/Rx';

@Injectable()
export class MyService {

 public ResultsSubject = new Subject<string>();

 public getResults() {
   this.ResultsSubject.next('data...');
 }

}

@Component({
  selector: 'my-cmpA',
  template: `
    <div>
      <h3>Component A</h3>
      <button (click)="_srvc.getResults()">trigger service!</button>
    </div>
  `,
})
export class AComp {
  constructor(private _srvc: MyService) { }
}

@Component({
  selector: 'my-cmpB',
  template: `
    <div>
      <h3>Component B</h3>
      <p>
        {{_results}}
      </p>
    </div>
  `,
})
export class BComp {

  _results = '';

  constructor(private _srvc: MyService) {
    this._srvc.ResultsSubject.subscribe(
      res => this._results = res,
      err => console.log(err)
    );
  }
}

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
    </div>
    <my-cmpA></my-cmpA>
    <my-cmpB></my-cmpB>
  `,
})
export class App {
  name:string;
  constructor() {
    this.name = 'Angular2'
  }
}

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ App, AComp, BComp ],
  providers: [MyService],
  bootstrap: [ App ]
})
export class AppModule {}
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks mxii, I tried your example and it worked. However I had issues with Subject in regard with http.get() where it returns an Observable<Response> and in Subject I defined Subject<Result[]> where Result was an own model. I tried it on several ways and could get it done so I decided to move on and merge the 2 components. Thanks though for your support!
yw! Sounds like you missed the .map() function. Anyway, gl! :)
No, I used the .map() function. This returns the Observable<Response>, however in Subject I defined Result[] as my type. Anyway :)
Your types are just for editing and compile-time checks .. during run-time there are no types! It's JavaScript! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.