My application is generated with latest @angular/cli.
Angular v.: 4.0.3, RxJS v.: 5.1, Zone.js: 0.8.4, Typescript: 2.2.2
I need to integrate CartoDB into my app. I created a service that will request and store data. Here it is:
// ========== carto.service.ts ==========
import {Injectable} from '@angular/core';
declare var cartodb: any;
@Injectable()
export class CartoService {
private _sql: any;
private _data: any;
constructor() {
this._data = this.getDataFromCarto('SELECT * FROM table');
}
get data() {
return this._data;
}
getDataFromCarto(query: string): any {
this._sql = new cartodb.SQL({user: username});
return this._sql.execute(query).done((data) => {
return data.rows;
}).error((errors) => {
console.error(`Was not able to get data: ${errors}`);
});
}
}
I did not found type definition for cartodb.js and was not able to write it myself. And so I just connected it as JS file and declared a new variable that matches carto`s global variable.
My component:
// ========== widget.component.ts ===========
import {Component, OnInit} from '@angular/core';
import {CartoService} from 'carto.service';
@Component({
selector: 'app-widget',
templateUrl: 'widget.component.html',
styleUrls: ['widget.component.scss']
})
export class WidgetTableComponent implements OnInit {
public data: any;
constructor(private carto: CartoService) {
super();
this.data = this.carto.data;
}
ngOnInit() {
}
}
And as a final step I want to show this data in template:
// ========= widget.component.html ==========
<tbody>
<tr *ngFor="let entry of data">
<th scope="row">{{entry.year}}</th>
</tr>
</tbody>
While data is not resolved I receive an object with callback. *ngFor should not iterate though it while data is not resolved successfully.
Solutions I tried:
- RxJS and Observable.subscribe() do not work. Angular thinks that asynchronous actions are only browser events, http requests and timers. Carto`s request is a Jquery callback I guess and not considered asynchronous.
- *ngIf doesn`t work also. It hides only when variable is equal to null. In my case 'data' equals to:
{"_callbacks":{"done":{"tail":{},"next":{"next":{}}},"error":{"tail":{},"next":{"next":{}}}}}
When response is received template will not be rendered again.
- Elvis operator (? to mark variable as optional) can be used only with params. If I used it like this it will cause template render error:
<tr *ngFor="let entry of data?">
- Async Pipe:
<tr *ngFor="let entry of (data | async)">
Will cause this error:
ERROR Error: Uncaught (in promise): Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe'
ngOnChanges doesn`t see my variable changed. It was not present in the output of:
ngOnChanges(changes) { console.log('All changes: ', changes); }
Did anyone encounter issue like this before? I would appreciate any help. Thanks in advance.