2

On Angular I write in the html template this code:

<div *ngFor='let itemArray of myObservableArray'>
  <div *ngFor='let item of itemArray | async'>
    {{item.value}}
  </div>
</div>

This is my app.component.ts:

import { Component } from '@angular/core';
import { MyService, MyDataType } from './app.service';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular 5';
  myObservableArray: Observable<MyDataType[][]>;

  constructor(private myService: MyService) {
    this.getData(2);
  }

  getData(id: number) {
    if (!this.myObservableArray) {
      this.myObservableArray = new Array<MyDataType[]>();
      this.myObservableArray[id] = this.myService.getData(id);
    }
  }
}

And this is the code of the app.service.ts:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class MyService {

  mydata: MyDataType[] = [
    {"id":1, "value":"value_1_1"},
    {"id":1, "value":"value_1_2"},
    {"id":2, "value":"value_2_1"},
    {"id":2, "value":"value_2_2"},
    {"id":3, "value":"value_3_1"},
    {"id":3, "value":"value_3_2"}
  ];

  constructor() { }

  getData(id: number):Observable<MyDataType[]>
  {
    let data = new Observable<MyDataType[]>(observer => {

          setTimeout(() => {
              observer.next(this.mydata.filter(i => i.id == id));
          }, 4000);
    });
    return data;
  }
}

export class MyDataType
{
  public id: number;
  public value: string;
}

The html template works correctly but I don't understand why the compiler give me this error:

Type 'MyDataType[][]' is not assignable to type 'Observable<MyDataType[][]>'.
      Property '_isScalar' is missing in type 'MyDataType[][]'.
    (property) AppComponent.myObservableArray: Observable<MyDataType[][]>

I think my initialization of the matrix is wrong but being quite new on Angular and TypeScript/JavaScript I would like help on how I can do it. On stackbliz I put the complete DEMO. Thanks.

3
  • 1
    probably because you declare myObservableArray: Observable<MyDataType[][]>; but then use this.myObservableArray = new Array<MyDataType[]>(); Commented Mar 29, 2018 at 15:52
  • @mast3rd3mon your comment does not help me. Could you tell me how I should initialize it if you know? Commented Mar 29, 2018 at 15:58
  • im pretty sure theres an ObservableArray which would be used as myObservableArray: ObservableArray<MyDataType[]>; Commented Mar 29, 2018 at 16:01

3 Answers 3

2

Finally I solved the problem declaring:

myObservableArray: Observable<Array<MyDataType[]>> = new Observable<Array<MyDataType[]>>();

and changing the getData method like the following:

getData(id: number) {
  if (!this.myObservableArray[id]) {
      this.myObservableArray[id] = this.myService.getData(id);
  }
}

and the html template in this way:

<div *ngFor='let item of myObservableArray[2]| async'>
    {{item.value}}
</div>

I have update the DEMO

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

Comments

0

I've forked your stackblitz and simplified your solution. Check out Live demo

app.service

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { interval } from 'rxjs/observable/interval';
import { map } from 'rxjs/operators';


@Injectable()
export class MyService {

  mydata: MyDataType[] = [
    {"id":1, "value":"value_1_1"},
    {"id":1, "value":"value_1_2"},
    {"id":2, "value":"value_2_1"},
    {"id":2, "value":"value_2_2"},
    {"id":3, "value":"value_3_1"},
    {"id":3, "value":"value_3_2"}
  ];

  constructor() { }

  // use interval with map instead of setTimeout
  getData(id: number): Observable<MyDataType[]> {
    return interval(5000).pipe(map(i =>this.mydata.filter(i => i.id == id)))
  }
}

app.component

import { Component } from '@angular/core';
import { MyService, MyDataType } from './app.service';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular 5';
  myObservableArray: Observable<MyDataType[]>;

  constructor(private myService: MyService) {
    this.getData(2);
  }

  getData(id: number) {
    // you do not needed nested arrays here
    this.myObservableArray = this.myService.getData(id);
  }
}

app.component.html

<p>
    Wait 5 seconds to see some magic happen :)
</p>

<div *ngFor='let item of myObservableArray | async'>
    {{item.value}}
</div>

1 Comment

Thanks for your answer, but you declare myObservableArray: Observable<MyDataType[]>; and this is an array, not a matrix, and isn't what I need.
0
import { Component } from '@angular/core';
import { MyService, MyDataType } from './app.service';
import { Observable } from 'rxjs/Observable';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular 5';

Here you declare myObservableArray as

Observable<MyDataType[][]

.

  myObservableArray: Observable<MyDataType[][]>;

  constructor(private myService: MyService) {
    this.getData(2);
  }

  getData(id: number) {
    if (!this.myObservableArray) {

But then you try to put

Array<MyDataType[]>() 

into it.

      this.myObservableArray = new Array<MyDataType[]>();
      this.myObservableArray[id] = this.myService.getData(id);
    }
  }
}

You can't put an

Array<MyDataType[]> 

into an

Observable<MyDataType[][]

This is what the compiler is trying to tell you.

2 Comments

Thanks for your answer. Finally I solved the problem declaring: myObservableArray: Observable<Array<MyDataType[]>> = new Observable<Array<MyDataType[]>>() and adapting the code.
Glad to hear that. It was a nice gesture if you would mark this post as solution, though. :)

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.