0

I'm having trouble passing in an object defined in my client controller to the server on a POST request. I'm passing it in a body in the service, but I'm getting a null error.

I believe that my controller is not passing the value to the service correctly, but I'm unsure what to add in order to pass it in correctly.

How can I pass the currentAction object to the action service correctly?

Here is the full code for reference: https://gist.github.com/KoryJCampbell/c57f7bc861d636a386023c4e55ed7624

Action Component

import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs';
import { User } from '../../_models';
import { Action } from '../../_models';
import { AuthenticationService } from '../../_services';
import { MatSort } from '@angular/material';
import { MatTableDataSource } from '@angular/material/table';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { ActionService } from '../../_services';
import { HttpClient } from '@angular/common/http';

export interface ActionView {
  actionName: string;
  actionType: string;
  primaryTable: string;
  specialUse: string;
  folder: string;
  actionDescription: string;
  actionTag: number;
  chartType: string;
  priority: number;
}

const ACTION_DATA: ActionView[] = [];

@Component({
  templateUrl: 'home.component.html',
})
export class HomeComponent implements OnInit, OnDestroy {

  // User Fields
  currentUser: User;
  users: User[] = [];
  currentUserSubscription: Subscription;

  // Action
  public currentAction: Action;
  actions: Action[] = [];
  currentActionSubscription: Subscription;

  displayedColumns: string[] = [
    'actionName', 'actionType', 'primaryTable',
    'specialUse', 'folder', 'actionDescription',
    'actionTag', 'chartType', 'priority',
  ];

  dataSource: any = new MatTableDataSource(ACTION_DATA);

  constructor(
    private authenticationService: AuthenticationService,
    private iconRegistry: MatIconRegistry,
    private sanitizer: DomSanitizer,
    private actionService: ActionService,
  ) {
    this.currentUserSubscription = this.authenticationService.currentUser
      .subscribe(user => {
        this.currentUser = user;
      });

    this.currentActionSubscription = this.actionService.currentAction
      .subscribe(action => {
        this.currentAction = action;
      });

    this.iconRegistry.addSvgIcon(
      'thumbs-up',
      this.sanitizer.bypassSecurityTrustResourceUrl('assets/img/examples/thumbup-icon.svg'),
    );
  }

  @ViewChild(MatSort) sort: MatSort;

  public getActions() {
    this.actionService.getActions(
      this.currentAction).subscribe((data) => {
        this.dataSource = data;
      });
  }

  ngOnInit() {
    this.dataSource.sort = this.sort;
    this.getActions();
  }

  ngOnDestroy() {
    // unsubscribe to ensure no memory leaks
    this.currentUserSubscription.unsubscribe();
  }
}

Action Service

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { User, Action } from '../_models';
import { BehaviorSubject, Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';

@Injectable({ providedIn: 'root' })
export class ActionService {

  public apiURL = 'http://localhost:15217/api/actions/launchactions';
  public currentUser: Observable<User>;
  public currentAction: Observable<Action>;
  private currentActionSubject: BehaviorSubject<Action>;

  constructor(private http: HttpClient) {
    this.currentActionSubject = new BehaviorSubject<Action>(JSON.parse(localStorage.getItem('currentAction')));
    this.currentAction = this.currentActionSubject.asObservable();
  }

  // Http Options
  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json',
    }),
  };

  getActions(action: Action): Observable<Action[]> {
    return this.http.post<Action[]>(this.apiURL,
      {
        SessionId: '22',
        // ActionTag: {test: 2},
        // Args: null
      })
      .pipe(
        retry(1),
        catchError(this.handleError),
      );
  }

  // Error handling
  handleError(error: any) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      // Get client-side error
      errorMessage = error.error.message;
    } else {
      // Get server-side error
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    window.alert(errorMessage);
    return throwError(errorMessage);
  }
}
AT82
  • 71,416
  • 24
  • 140
  • 167
kjamp
  • 365
  • 3
  • 10
  • 37
  • Have you tried changing it to: `public apiURL = 'http://localhost:15217/api/actions/launchaction';` (without the "s" at the end)? – crgolden Aug 27 '19 at 08:17
  • Yeah, I tried that; still running into the same issue – kjamp Aug 27 '19 at 08:27
  • If you drop a `console.log(action)` in your `this.currentActionSubscription` subscription, what do you get back? – Andrew Hill Aug 27 '19 at 08:35
  • action is null! hmm so i'm not passing in the action to the service... but i'm unsure of where that action would be defined and how in the component – kjamp Aug 27 '19 at 08:37
  • race condition, `getActions()` is called before `this.currentAction` has been given a value. Suggested reading: https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call to understand the asynchronous world of Javascript :) – AT82 Aug 27 '19 at 12:09

0 Answers0