Whenever I use afDB.list('/path') method, I get the following:
console.log(this.items);
and I have this example as my firebase database: listings file
surprisingly, editing the data works perfectly fine (e.g. remove(), push(),... etc.), but I can't seem to be able to retrieve it; however, I can access it. I thought it might be a rules issue, yet, my rules are fine: firebase Rules
this is the portion of the code that I'm having trouble with:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { AngularFireAuth } from 'angularfire2/auth';
import { FirebaseProvider } from '../../providers/firebase/firebase';
import { AngularFireDatabase } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import * as firebase from 'firebase/app';
//import { ListingDetailsPage } from '../listing-details/listing-details';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
items: Observable<any[]>;
constructor(
public navCtrl: NavController,
public afAuth: AngularFireAuth,
public firebaseProvider: FirebaseProvider,
public afDB: AngularFireDatabase
) {
this.items = afDB.list('/listings', ref => ref.orderByChild('age').equalTo('large')).valueChanges();
}
login(){
this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider()).then(res => console.log(res));
}
logout() {
this.afAuth.auth.signOut();
}
list(){
console.log(this.items);
}
}
I also tried to use AngularFireList instead of Observable, but it doesn't change the issue. I also used afDB.object() instead of afDB.list(), I still get the same problem. Query is not the issue either, as I tried to use a simple .list()/.object() and again the same issue. additionally, I created a database using the same code (.set()), and I couldn't retrieve it either.
Relevant Specs:
"angularfire2": "^5.0.0-rc.11",
"firebase": "^5.2.0",
"promise-polyfill": "^8.0.0",
"ionic-angular": "3.9.2",
"#angular/compiler-cli": "5.2.11",
"#angular/core": "5.2.11",
OS: Windows10
platforms tested: Google Chrome Browser/ Firefox Browser/ Android SDK emulator
You've defined your items variable as an observable (and that is correct) but if you want to play with the data returned from that observable, you need to subscribe to that observable.
constructor(
public navCtrl: NavController,
public afAuth: AngularFireAuth,
public firebaseProvider: FirebaseProvider,
public afDB: AngularFireDatabase
) {
this.items = afDB.list('/listings', ref => ref.orderByChild('age').equalTo('large')).valueChanges();
this.items.subscribe( valueOfItems => {
console.log(valueOfItems);
})
}
There is a compatibility issue in Angularfire2 with rxjs. So, until Angularfire2 provide support for rxjs6, you can resolve this error by installing rxjs-compat package using below command.
npm install rxjs#6 rxjs-compat#6 --save
you can find more information in the rxjs migration guide.
https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/v6/migration.md
there is also a "template driven" way to retrieve data.
Template :
// example 1
<ul>
<li *ngFor="let dino of dinosaurs$ | async">
<p>{{vdino.name }}</p>
</li>
</ul>
// example 2
<ul>
<li *ngFor="let dino of dinosaursArray">
<p>{{vdino.name }}</p>
</li>
</ul>
Controller :
constructor(private afDb: AngularFireDatabase) {
const itemsRef: AngularFireList<any> = afDb.list('dinosaurs');
// example 1
this.dinosaurs$ = itemsRef.valueChanges();
// example 2
this.dinosaurs$.subscribe(array => this.dinosaursArray = array);
}
Here a stackblitz with the two examples (credits to #markgoho) :
https://stackblitz.com/edit/angular-trrnhg
The deps are a bit outdated but it still should work for you.
Moreover, #JeremyW answer should work, can you be more specific on the error ?
EDIT : " error: TypeError: Object(...) is not a function"
If you face this error, this is likely a compatibility problem with rxjs 5, you may try with rxjs 6.
check this post :
Angular2 fire listen to node changes throws an error
Related
I am following a tutorial which is clearly outdated. But I tried my best to follow up with the migration guide but I am still stuck with this one little error.
import { Injectable } from '#angular/core';
import { AngularFireList, AngularFireObject, AngularFireDatabase } from 'angularfire2/database';
import { ExpenseModel } from './expense-model';
#Injectable()
export class ExplistService {
private basePath = '/UD';
explist: AngularFireList<ExpenseModel[]> = null; // list of objects
exp: AngularFireObject<ExpenseModel> = null;
createExpenseModel(exp: ExpenseModel): void {
this.explist.push(exp)
.catch(error => this.handleError(error));
}
I am getting the error at the line
this.explist.push(exp)
Argument of type 'ExpenseModel' is not assignable to parameter of type
'ExpenseModel[]'. Property 'includes' is missing in type
'ExpenseModel'.
Hi I am building a toDo app and i ran into this problem after i completed all of the steps.
error---
Runtime Error
Can't resolve all parameters for TaskListPage: ([object Object], ?).
Stack
import { Component } from '#angular/core';
import { NavController, ItemSliding } from 'ionic-angular';
import {Task} from './task';
import {AngularFire, FirebaseListObservable} from 'angularfire2';
#Component({
selector: 'page-tasklist',
templateUrl: 'tasklist.html'
} )
export class TaskListPage {
tasks: FirebaseListObservable <any[]>;
constructor(public navCtrl: NavController, af: AngularFire) {
this.tasks = af.database.list('/tasks');
}
addItem() {let theNewTask: string = prompt("New Task");
if (theNewTask !== '')
{ this.tasks.push({ title: theNewTask, status: 'open'});
}
}
markAsDone( slidingItem: ItemSliding, task: Task)
{ this.tasks.update(task.$key, {status: 'done'});
slidingItem.close();
}
removeTask(slidingItem: ItemSliding, task: Task)
{ this.tasks.remove(task.$key);
slidingItem.close();
}
}
This is a place where Angular can really improve its error messaging. The offending line is this one:
constructor(public navCtrl: NavController, af: AngularFire) {
You have no access modifier on the af variable, so it is assumed to be a call-time variable (no public, protected or private, so Angular does not know it is supposed to be a class member variable). Since at compile time, what af will be is not known, it results in that warning.
The simple solution is: add an access modifier on the variable. If it is not meant to be shared, private is usually the appropriate modifier.
Also, AngularFire does not look like a valid export from angularfire2. It looks like it should be either AngularFirestore or one of the functionality specific modules - auth, messaging, etc. Also make sure you have set up your AngularFireModule in your app.module, by following the setup directions in their repo.
I'm a total newbie into Angular/Typescript web development.
I'm developing a website using ASP.NET Core 2.0 and Angular 4. It needs to fetch some data and present it at the homepage (that would be the home component of the Angular app). I've seen some examples and they suggest doing something like this:
import { Component, Inject } from '#angular/core';
import { Http } from '#angular/http';
#Component({
selector: 'quotes',
templateUrl: './quotes.component.html'
})
export class FetchDataComponent {
public quotes: Quote[];
constructor(http: Http, #Inject('BASE_URL') baseUrl: string) {
http.get(baseUrl + 'api/quotes/recent').subscribe(result => {
this.quotes = result.json() as Quote[];
}, error => console.error(error));
}
}
interface Quote {
text: string;
author: string;
timeStamp: Date;
}
That code works fine when the component is not the first one to be presented when the page is loaded. If I try to fetch data on the home component, the server freaks out and throws all kind of exceptions. First, it throws a TaskCancelledException, and further requests throw:
NodeInvocationException: Prerendering timed out after 30000ms because the boot function in 'ClientApp/dist/main-server' returned a promise that did not resolve or reject.
I'm assuming that I'm doing stuff very wrong, but I haven't seen any other way of doing what I want.
I tried moving the offending code (the http.get request) to a separate function, but now I don't know how am I supposed to call it when the component finished loading.
import { Component, Inject } from '#angular/core';
import { Http } from '#angular/http';
#Component({
selector: 'quotes',
templateUrl: './quotes.component.html'
})
export class FetchDataComponent {
public quotes: Quote[];
private ht: Http;
private url: string;
constructor(http: Http, #Inject('BASE_URL') baseUrl: string) {
this.ht = http;
this.url = baseUrl;
}
fetchQuotes(): void {
this.ht.get(baseUrl + 'api/quotes/recent').subscribe(result => {
this.quotes = result.json() as Quote[];
}, error => console.error(error));
}
}
interface Quote {
text: string;
author: string;
timeStamp: Date;
}
No http event has helped me. I can make everything work using the (click)="" directive, but obviously, I don't want the user to have to click something for the app to work as expected. No other directive seems to work either.
Below is the code I have on the html of the component:
<p class="warning" *ngIf="!quotes" (click)="fetchQuotes()">
<span class="glyphicon glyphicon-warning-sign"></span>
<em>There's nothing to show yet.</em>
</p>
<div *ngIf="quotes">
<ul class="quoteList" *ngFor="let quote of quotes">
<li>
{{ quote.text }}
<small>{{ quote.author }}, {{ quote.timeStamp }}</small>
</li>
</ul>
</div>
So to summarize, I need a way to fetch data for the component that Angular will show by default upon loading the page.
So to summarize, I need a way to fetch data for the component that
Angular will show by default upon loading the page.
The typical way to do this is to implement the Angular OnInit interface, which allows you to do initialization in the ngOnInit() callback method.
import { OnInit } from "#angular/core";
// ...
export class FetchDataComponent implements OnInit {
ngOnInit() {
// do initial data load here
}
}
I am currently loading a list of people randomly taken from the randomuser.me api.
When I turn my internet connection off, I'm simply getting a net::ERR_INTERNET_DISCONNECTED error.
In a "no internet" case I would like to somehow save the http get request and when the connection turns on again, automatically call the saved request. Is that possible ?
Hope I'm clear enough.
Thanks
You can use Network plugin. more info here
for example:
1-create a service to check the connectivity and add this to app.module.ts providers, so you can access it from everywhere:
import { Injectable } from '#angular/core';
import { Platform } from 'ionic-angular';
import { Network } from 'ionic-native';
#Injectable()
export class ConnectivityService {
onDevice: boolean;
constructor(
private platform: Platform
) {
this.onDevice = this.platform.is('cordova');
}
isOnline(): boolean {
if (this.onDevice && Network.type !== 'none') {
return true;
} else {
return navigator.onLine;
}
}
}
2- in your .ts file
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
//service
import { ConnectivityService } from '../../providers/connectivity.service';
#Component({
templateUrl: 'page.html',
})
export class Page {
constructor(
private nav: NavController,
private cs: ConnectivityService
) {}
onCallAPI() {
if (this.cs.isOnline()) {
//do somthing
}
}
}
3- finally if you need to check until your device become online again, you need to add a connectivity listener.
AngularJs 2 with Webpack.
I am not able to connect to NYT Api.
ALL ENDOPOINTS TESTED AND WORKING PROPERLY
AngularJs 2 in production mode:
enableProdMode();
App:
-1 component
-1 Service
All other components working/displaying properly.
No other services on app yet.
Service returns with error: (in console)
error: "Collection 'topstories' not found"
The Service
import { Injectable } from '#angular/core';
import { Http, Headers, URLSearchParams, Response } from '#angular/http';
import 'rxjs/add/operator/toPromise';
import { Observable } from 'rxjs';
#Injectable()
export class NewsService {
private topStoriesUrl: string = `https://api.nytimes.com/svc/topstories/v2/politics.json`;
// private topStoriesUrl: string = `https://newsapi.org/v1/articles`;
// Injecting Http capabilities
constructor( private http: Http ) {}
// for error handling
private handleError(error: any): Promise<any>{
console.error("FromSERVICE:::---:::--> ", error);
return Promise.reject( error.message || error );
}
getNews(): Observable<any> {
let parms: URLSearchParams = new URLSearchParams();
parms.set("api-key", "184db335652341518bea3e4a5db85494");
// parms.set("source", "associated-press");
// parms.set("apiKey", "e4e2aa62a883464a87547e8de4336f61");
return this.http.get( this.topStoriesUrl, { search: parms } )
.map( (res: Response) => res['articles'] )
.catch( this.handleError );
}
}
The Component
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { Observable } from 'rxjs';
// service for fetcing news from api
import { NewsService } from '../services/news.service';
#Component({
selector: 'main-news',
templateUrl: '../templates/main-news.component.html'
})
export class MainNewsComponent implements OnInit{
private news: Observable<any>;
constructor(
private router: Router,
private newsService: NewsService
) {}
ngOnInit(): void {
this.newsService.getNews().subscribe( {
next: r => this.news = Observable.of<any[]>(["one"]),
error: err => console.error("From COMPONENT--->", err)
} );
}
}
I have tried this call with both Api from different organizations to get
the same error on the URL resource.
I have tried this same call with said URL with a Ruby script (NET/http) and also directly on the browser address bar, to receive a VALID response on these BOTH cases.
NOT SURE WHY IT FAILS WITH ANGULAR.
HELP!!!
From your console error it looks like the url is not found on server.
The error displayed is returned from server its not angularjs specific error.
Notice 404 not found returned.
So check your url and server again.
Turns out I was missing the:
Access-control-allow-origin
header.
Go figure!
Apparently, it is not added automatically by AngularJs 2.
Thanx