0

I'm facing difficulties with simple Angular/Java application. During rest call, I'm also creating a tile component. Data is being retrived - I can see logs in the network tab and in backend logs, however Tile component is not being created. Here is the code:

main.grid.ts:

@Component({
  templateUrl: './main.html',
  selector: 'album-grid',
})
export class MainGrid implements OnInit {

  private tileDtos: TileDto [];
  private album: AlbumDto [];

  constructor(public dialog: MdDialog, private albumService: AlbumService, private tileUtils: TileUtils) {
    this.album=[];
    this.tileDtos=[];
  }

  ngOnInit(): void {
   this.albumService.getAllAlbums().subscribe(p => this.album = p); // here is the call to rest service
    console.log("@@@@@@@@@@@@@  "+ this.album.length); // this returns 0
    this.tileDtos = this.tileUtils.buildTile(this.album);
    console.log("@@@@@@@@@@@@@  "+ this.tileDtos.length); // this returns 0
  }

}

album.service.ts:

@Injectable()
export class AlbumService {
  private baseUrl = 'http://localhost:8080';

  constructor(private http: Http) {
  }

  getAllAlbums(): Observable<AlbumDto[]> {
    let getUrl = `${this.baseUrl}/getAllAlbums`;
    return this.http.get(getUrl, {headers: AlbumService.getHeaders()}).map(mapAlbums);
  }

  private static getHeaders() {
    let headers = new Headers();
    headers.append('Accept', 'application/json');
    return headers;
  }
}

function mapAlbums(response: Response): AlbumDto[] {
  let json = response.json();
  let album: AlbumDto[] = json.map(toAlbum);
  return album;
}

function toAlbum(r: any): AlbumDto {
  let album = <AlbumDto>({
    id: r.id,
    albumName: r.albumName,
    owner: r.owner,
    images: r.images,
  });
  console.log("album: ",album);
  return album;
}

in the logs on frontend side I can see:

@@@@@@@@@@@@@  0
Building tile
@@@@@@@@@@@@@  0
album: //here I'm seeing full album json populated as it should be.

Edit.

To narrow the issue, to my understanding the issue is with the order of loading in the Main.Grid.ts. as I've noticed in the logs, the rest call is being triggered after the code to create the tile element. I've tried to use hardcoded json object, and it was loaded properly.

2
  • 2
    Please create a minimal reproduction. There seems to be too much clutter in your code which is not related to your actual question. By isolating the problem, you're likely to find the solution yourself (and learn a couple of things along the way). Commented Oct 1, 2017 at 8:59
  • Ok. I see your point, I just thought that providing background is a good idea, clearly I failed with it = ). Please see my update. Commented Oct 1, 2017 at 16:33

2 Answers 2

2

You are attempting to log and use the updated value of this.album before it has been updated. Take another look at the code you have above:

ngOnInit(): void {
    this.albumService.getAllAlbums().subscribe(p => this.album = p); // here is the call to rest service
    console.log("@@@@@@@@@@@@@  "+ this.album.length); // this returns  
    this.tileDtos = this.tileUtils.buildTile(this.album);
    console.log("@@@@@@@@@@@@@  "+ this.tileDtos.length); // this returns 0
}

The code p => this.albums = p is going to run asynchronously once the network call completes. Immediately after invoking this asynchronous operation, you attempt to use this.album, which will not have been updated yet. Here's a breakdown:

  1. You instruct Angular to make a network call, providing it a function to invoke once the data is returned.
  2. Before Angular has a chance to make the request, you attempt to access this.album, which has not yet been updated and remains as an empty array.
  3. Some time later, Angular returns with the data and invokes your callback function, which updates this.album but does not update this.tileDtos.

To fix this issue, you need run to the relevant code in the correct order. e.g.:

ngOnInit(): void {
    this.albumService.getAllAlbums().subscribe(p => {
        this.album = p; // here is the call to rest service
        console.log("@@@@@@@@@@@@@  "+ this.album.length); // this returns  
        this.tileDtos = this.tileUtils.buildTile(this.album);
        console.log("@@@@@@@@@@@@@  "+ this.tileDtos.length); // this returns 0
    });
}

As you can see, this will ensure that the value of this.album is set correctly before attempting to use it to update your component.

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

Comments

0

Does :

this.albumService.getAllAlbums().subscribe(p => this.album = p);

return a promise? You'd need to attach it to a .then() and do your work there.

1 Comment

Sorry I'm quite new in Angular world, what do you mean by returning a promise? I've used this code in different "application" and it worked fine ie. returned data and put it in html tab.

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.