0

I have an Angular7 frontend and Laravel backend. I tested the endpoints on POSTMAN and it works very well. However when I tested on the Serve, it loaded nothing, and I got this error.

I did log.console and I got this error:

ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed

error screenshot

postmanscrrenshot

ApiController:

public function indexSmsmt()
{
    $smsmts = Smsmt::all();
    return response()->json(['success' => true,'data'=>$smsmts], $this->successStatus);
}

public function showSmsmt($id)
{
    $smsmt = Smsmt::find($id);
    if (is_null($smsmt)) {
        return $this->sendError('SMS Incoming not found.');
    }

    return response()->json(['success' => true,'data'=>$smsmt], $this->successStatus);
}

public function storeSmsmt(Request $request)
{
    $smsmt = Smsmt::create($request->all());
    return response()->json(['success' => $smsmt], $this-> successStatus);
}

public function editSmsmt($id)
{
    $smsmt = Smsmt::find($id);
    return response()->json(['success' => true,'data'=>$smsmt], $this->successStatus);
}

public function updateSmsmt(Request $request, $id)
{
    $smsmt = Smsmt::find($id);
    $smsmt = $smsmt->update($request->all());
    return response()->json(['success' => true,'data'=>$smsmt], $this->successStatus);
}

public function deleteSmsmt($id)
{
    $smsmt = Smsmt::find($id)->delete();
    return response()->json(['success' => true], $this->successStatus);
}

environment.prod.ts

export const environment = {
    production: true,
    apiUrl:   'http://exampl.com/api',
};

smsmt.service.ts

import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { Smsmt } from '../models/smsmt';
import { environment } from 'src/environments/environment.prod';

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

@Injectable({
    providedIn: 'root'
})

export class SmsmtService {
    private API_URL= environment.apiUrl;
    constructor(private http: HttpClient) { }

    getSmsmts (): Observable<Smsmt[]> {

        return this.http.get<Smsmt[]>(this.API_URL + '/indexSmsmt')
        .pipe(
            tap(smsmts => console.log('Fetch smsmts')),
            catchError(this.handleError('getSmsmts', []))
        );
    }

    getSmsmt(id: number): Observable<Smsmt> {

        const url = this.API_URL + '/editSmsmt' + '/{id}';

        return this.http.get<Smsmt>(url).pipe(
            tap(_ => console.log(`fetched smsmt id=${id}`)),
            catchError(this.handleError<Smsmt>(`getSmsmt id=${id}`))
        );
    }

    addSmsmt (smsmt): Observable<Smsmt> {
        return this.http.post<Smsmt>(this.API_URL + '/storeSmsmt', smsmt, 
            httpOptions).pipe(
                tap((smsmt: Smsmt) => console.log(`added smsmt w/ id=${smsmt.id}`)),
                catchError(this.handleError<Smsmt>('addSmsmt'))
            );
    }

    updateSmsmt (id, smsmt): Observable<any> {
        const url = this.API_URL + '/updateCSmsmt' + '/{id}';
        return this.http.put(url, smsmt, httpOptions).pipe(
            tap(_ => console.log(`updated smsmt id=${id}`)),
            catchError(this.handleError<any>('updateSmsmt'))
        );
    }

    deleteSmsmt (id): Observable<Smsmt> {
        const url = this.API_URL + '/deleteSmsmt' + '/{id}';

        return this.http.delete<Smsmt>(url, httpOptions).pipe(
            tap(_ => console.log(`deleted smsmt id=${id}`)),
            catchError(this.handleError<Smsmt>('deleteSmsmt'))
        );
     }

    private handleError<T> (operation = 'operation', result?: T) {
        return (error: any): Observable<T> => {

            // TODO: send the error to remote logging infrastructure
            console.error(error); // log to console instead

            // Let the app keep running by returning an empty result.
            return of(result as T);
        };
    }
}

smsmt.component.ts

import { Component, OnInit } from '@angular/core';
import { SmsmtService } from '../../../services/smsmt.service';
import { Router } from '@angular/router';
import { Smsmt } from '../../../models/smsmt';

@Component({
    selector: 'app-bulk-sms-outbox',
    templateUrl: './bulk-sms-outbox.component.html',
    styleUrls: ['./bulk-sms-outbox.component.scss']
})

export class BulkSmsOutboxComponent implements OnInit {
    displayedColumns: string[] = ['msisdn', 'message', 'telco','error_message','error_code', 'package_id'];
    data: Smsmt[] = [];
    isLoadingResults = true;    
    constructor(private api: SmsmtService) { }

    ngOnInit() {
        this.api.getSmsmts()
            .subscribe(res => {
                this.data = res;
                console.log(this.data);
                this.isLoadingResults = false;
            }, err => {
                console.log(err);
                this.isLoadingResults = false;
            });
    }

    ngOnDestroy(): void {
        document.body.className = '';
    } 
}

component.html

<tr  *ngFor="let datas of data| paginate: { itemsPerPage: 5, currentPage: p }; let i = index">
    <td>{{i + 1}}</td>
    <td>{{datas.msisdn}}</td>
    <td>{{datas.short_code_called}}</td>
    <td>{{datas.package_id}}</td>
    <td>{{datas.error_message}}</td>
    <td>{{datas.error_code}}</td>
</tr>

Nothing is being loaded.

How do I resolve this issue?

2
  • explain in detail what you really need and what is the actual result Commented Jun 12, 2019 at 11:38
  • I want to display the data in component.html. But nothing is coming out Commented Jun 12, 2019 at 11:48

1 Answer 1

1

When fetching the data in Laravel, you're doing

return response()->json(['success' => true,'data'=>$smsmts], $this->successStatus);

And returns an object with an Array INSIDE of that object Somethig like:

{
   "sucess":"bla bla bla";
   "data":[ ... ] <- Here
}

The data you want to display is in that variable data

In the file smsmt.service.ts, the method 'getSmsmts()' receives an Array of Smsmts[] ( this.http.get<Smsmt[]>), but it's NOT what you are sending from the backend.

The backend sends an OBJECT (with an Array inside) but the http.get() is waiting for an ARRAY. That's why it throws the error.

You should receive the http.get() method receive an object, like this:

getSmsmts (): Observable<any> { // Change here to any
    return this.http.get<any>(this.API_URL + '/indexSmsmt') // and here too
    .pipe(
        tap(smsmts => console.log('Fetch smsmts')),
        catchError(this.handleError('getSmsmts', []))
    );
}

Now, in the smsmts.component.ts file, try this:

ngOnInit() {
    this.api.getSmsmts()
        .subscribe(res => {
            this.data = res.data; // change 'res' to 'res.data'
            console.log(this.data);
            this.isLoadingResults = false;
        }, err => {
            console.log(err);
            this.isLoadingResults = false;
        });
}

This may work. Not used to work with .pipe and .taps, but it should work. Note that this is a workaround, it's not recomended to receive and return any. You could make an interface like "RequestResponse" with two atributes : sucess and data and that way, you avoid using the any type

Sign up to request clarification or add additional context in comments.

12 Comments

When I changed 'res' to 'res.data', it underline it as red and I got another error: any Property 'data' does not exist on type 'Smsmt[]'.ts(2339)
Try to change the '.subscribe(res => { .... })' to .subscribe((res: any) => { ... })'. This will remove the underline, and probably solve the issue
Change the return type of the service 'getSmsmts()' to Observable<any> aswell. The thing is, the method returns an Array, but the backend sends a response, with the array inside of it. That's why the errors
I am very sorry. Please am a bit bit confused. Can you help me update your answer in the code
Yes , I can, but wait a bit, because im on my phone xD let me reach my office and i'll explain :)
|

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.