SBB
SBB

Reputation: 8970

Angular - When observable is complete, do something

I have a 2 part process that I am working with.

Component 1 allows me to import a list of usernames and submit it to a service. That service then returns the user profile data which I use in Component 2.

My issue is that I am trying to do something when I receive the data back from the observable I am subscribed to but it doesn't appear to be firing.

Component 1:

import { Component, EventEmitter, NgModule, OnInit, Output } from '@angular/core';
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MassEmpService } from "app/mass-change/shared/mass.service";
import { Observable } from 'rxjs/Observable';

@Component({
    selector: 'app-import-list',
    templateUrl: './import-list.component.html',
    styleUrls: ['./import-list.component.css'],
})
export class ImportListComponent implements OnInit {

    // Define the data types used for the import list
    importForm: FormGroup;
    message: {};
    error: string;

    constructor(
        private fb: FormBuilder,
        private _massEmpService: MassEmpService
    ) {
    }

    ngOnInit() {
        this.createForm();
    }

    // Generate the form
    createForm() {
        this.importForm = this.fb.group({
            dataType: ['-1', Validators.required],
            data: ['', Validators.required]
        });
    }

    // Process the data for the form
    onProccess(data) {

        // Define our vars
        let i: number;
        const dat: string = data.data.split('\n');
        const dataType: string = data.dataType;
        const validArray = [];
        const invalidArray = [];

        // Loop over each line
        for (i = 0; i < dat.length; i++) {
            // Validate our data point
            if (this.validateData(dataType, dat[i])) {
                validArray.push(dat[i]);
            } else {
                invalidArray.push(dat[i]);
            }
        }

        // Do we have any invalid data?
        if (invalidArray.length) {
            this.renderMessage('danger', 'fa-warning', 'Oops! Please check for invalid data.', false);
        } else {
            // Receive the data based on the imported criteria.
            this._massEmpService.processImport(dataType, validArray)
                .subscribe(
                    data => { this._massEmpService.fetchImportedResults(data); },
                    error => { this.error = error.statusText; }
                );

        }
    }
... Other Code Here ...
}

Component 2:

export class EmployeeSelectionComponent implements OnInit {

    // Define our search results
    public searchResults: ImportResults[] = [];

    constructor(
        private _massEmpService: MassEmpService
    ) {
    }

    ngOnInit() {
        this.fetchData();
    }

    fetchData() {
        // Push our results to the array if they don't already exist
        this._massEmpService.importedResults
        .subscribe(
            data => {
                this.searchResults.push(...data);
                console.log('I made it here');
            },
            () => {
                console.log('.. but not here');
            }
        );
    }
}

Service:

import { Injectable } from '@angular/core';
import { Http, Response, Headers } from '@angular/http';
import { RouterLink } from '@angular/router';
import { FrameworkService } from '@aps/framework';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class MassEmpService {

    // API URL
    baseUrl = 'https://internal/api';

    // Define the token headers for the service calls
    headers: Headers = new Headers({
        "Authorization": this._frameworkService.getSessionInfo().token
    });

    // Create a subject to observe the results and changes over time
    public importedResults = new Subject<any>();
    public transitionFields = new Subject<any>();

    constructor(
        private _http: Http,
        private _frameworkService: FrameworkService
    ) { }

    // Given a dataset, return the users based on data points submitted
    processImport(dataType, dataSet): Observable<any> {
        return this._http.post(this.baseUrl + '/fetchEmployeesFromImport', { "dataType": dataType, "data": dataSet }, { "headers": this.headers })
            .map((result: Response) => result.json())
            .share()
            .catch(this.handleError);
    };

    // Pass the data received from the import process through our subject to observe
    fetchImportedResults(data){
        this.importedResults.next(data);
    }

}

The Question:

In component 2, I am trying to check when I get data back so I can do something else in that component. I don't seem to reach the completed part of the observable though.

Any thoughts as to what I am doing wrong?

Upvotes: 8

Views: 15001

Answers (1)

cartant
cartant

Reputation: 58400

The first part of the problem lies in this snippet:

this._massEmpService.importedResults
.subscribe(
    data => {
        this.searchResults.push(...data);
        console.log('I made it here');
    },
    () => {
        console.log('.. but not here');
    }
);

The second callback you are passing is for error notifications - not completion notifications. You will need to pass an additional callback to handle completion notifications.

The second part of the problem is that importedResults is a Subject and as such won't complete until its complete method is called. And there is no indication in the snippets that you are calling that method.

Upvotes: 7

Related Questions