Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 705
SBB Avatar asked Jul 10 '17 23:07

SBB


1 Answers

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.

like image 176
cartant Avatar answered Sep 24 '22 19:09

cartant