Angular - ERROR Error: Ошибка при попытке изменить '[объект объекта]'.Разрешены только массивы и итерации - PullRequest
0 голосов
/ 12 июня 2019

У меня есть внешний интерфейс Angular7 и внутренний интерфейс Laravel. Я проверил конечные точки на POSTMAN, и он работает очень хорошо. Однако когда я тестировал на Серве, он ничего не загружал, и я получил эту ошибку.

Я сделал log.console и получил эту ошибку:

ОШИБКА Ошибка: ошибка при попытке изменить '[объект объекта]'. Разрешены только массивы и итерации

скриншот с ошибкой

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>

Ничего не загружается.

Как мне решить эту проблему?

1 Ответ

0 голосов
/ 12 июня 2019

При извлечении данных в Laravel вы выполняете

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

и возвращаете объект с массивом INSIDE этого объекта. Пример:

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

Данные, которые вы хотитедля отображения находится в этой переменной data

В файле smsmt.service.ts , метод 'getSmsmts ()' получает массив Smsmts[] (this.http.get<Smsmt[]>),но это НЕ то, что вы отправляете из бэкэнда.

Бэкэнд отправляет ОБЪЕКТ (с массивом внутри), но http.get () ожидает Массив.Вот почему он выдает ошибку.

Вы должны получить метод http.get () для получения объекта, например так:

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', []))
    );
}

Теперь, в smsmts.component.ts file, попробуйте это:

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;
        });
}

Это может работать.Не используется для работы с .pipe и .taps, но должно работать.Обратите внимание, что это обходной путь, не рекомендуется получать и возвращать any.Вы можете создать интерфейс типа «RequestResponse» с двумя атрибутами: sucess и data , и таким образом вы избежите использования any type

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...