I'm trying to incorporate a Firebase database into my Ionic application using Angular. I was following the instructions laid out on the AngularFire github page (https://github.com/angular/angularfire2) but when I actually run the application I keep getting a null response. I also am confused on the input of the of the db.object method (db.object('item')). What does 'item' actually represent?
This is my app.component.ts file
import { Component } from '#angular/core';
import { Platform } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { MenuController } from '#ionic/angular';
import { AngularFireDatabase } from '#angular/fire/database';
import { Observable } from 'rxjs';
#Component({
selector: 'app-root',
templateUrl: 'app.component.html'
})
export class AppComponent {
item: Observable<any>;
example: Observable<any>;
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private menu: MenuController,
private db: AngularFireDatabase
){
this.item = db.object('item').valueChanges();
this.initializeApp();
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
close(){
this.menu.close();
}
}
This is my app.component.html file
<ion-app>
<ion-menu side="start" menuId="first">
<ion-header>
<ion-toolbar color="primary">
<ion-title>Hi</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item [routerLink]="['/orders']" routerLinkActive="active" (click)="close()" >My Orders</ion-item>
<ion-item [routerLink]="['/apps']" routerLinkActive="active" (click)="close()">My</ion-item>
<ion-item [routerLink]="['/pres']" routerLinkActive="active" (click)="close()">My</ion-item>
<ion-item>{{ (item | async)?.name }}</ion-item>
</ion-list>
<li class="text" *ngFor="let item of items | async">
{{ item | json }}
</li>
</ion-content>
</ion-menu>
<ion-router-outlet main></ion-router-outlet>
</ion-app>
This is my app.module.ts file
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { RouteReuseStrategy } from '#angular/router';
import { FormsModule } from '#angular/forms';
import { IonicModule, IonicRouteStrategy } from '#ionic/angular';
import { SplashScreen } from '#ionic-native/splash-screen/ngx';
import { StatusBar } from '#ionic-native/status-bar/ngx';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { AngularFireModule } from '#angular/fire';
import { environment } from '../environments/environment';
import { AngularFirestoreModule } from '#angular/fire/firestore';
import { AngularFireDatabaseModule } from '#angular/fire/database';
import { AngularFireAuthModule } from '#angular/fire/auth';
#NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [BrowserModule, FormsModule, IonicModule.forRoot(), AppRoutingModule, AngularFireModule.initializeApp(environment.firebase), AngularFireDatabaseModule, AngularFireAuthModule],
providers: [
StatusBar,
GooglePlus,
SplashScreen,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule {}
Image of my Firebase database. This is what can be seen right underneath my app name: https://pasteboard.co/HTxY5eC.png
Hi Kiran and welcome to SO. You went way overkill on how much information you provided, but rather be safe than sorry - right?
In the example you're looking at item is the node in the database. I take it you're also fairly new to Firebase, so I won't assume anything.... Have you played around with the Firebase console yet? (https://console.firebase.google.com/project/PROJECT_NAME/database/PROJECT_NAME/data) The view that allows you to see the contents of your Real-Time Database? Play around in there and add a few "nodes" in the database. They have nicely coordinated colors for when you add, edit, and remove data... pretty cool, right? Now erase your test nodes and create a node named "item", and add a few child nodes.
In your code this.item = db.object('item').valueChanges(); listens to the changes in the information stored in the item node of your database... and sticks it into the this.item variable. Your HTML file loops over any contents of the this.item variable and displays it via *ngFor="let item of items | async
So long story short - your original question... item isn't anything special - make it whatever you call your database node. You're getting null because right now you are missing a node in your DB with a matching name of item
Related
I am trying too code a very basic Weather app that pulls data from this API https://openweathermap.org/api. When I click the link too go from the home.html file too the weatherData.html nothing is showing up and I cant seem too pinpoint the issue within my code,any help would be appreciated.
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>
Weather Ireland
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Weather Ireland</ion-title>
</ion-toolbar>
</ion-header>
<a class="button icon-right ion-plus-round" href="../weather-data/weather-data.page.html">weatherData</a>
</ion-content>
This is the code for the homepage.html which links too the weatherData.html file where the information from the API is supposed to be printed.
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { IonicModule } from '#ionic/angular';
import {WeatherDataService} from '../weather-data.service'
import { WeatherDataPageRoutingModule } from './weather-data-routing.module';
import { WeatherDataPage } from './weather-data.page';
#NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
WeatherDataPageRoutingModule
],
declarations: [WeatherDataPage]
})
export class WeatherDataPageModule {
weather;
constructor(private weatherdataservice: WeatherDataService){}
ngOnInit(){
this.weatherdataservice.getWeather().subscribe((data)=>{
console.log(data);
this.weather = data['weather'];
}
)
}
}
This is the code for the data.html file
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { FormsModule } from '#angular/forms';
import { IonicModule } from '#ionic/angular';
import {WeatherDataService} from '../weather-data.service'
import { WeatherDataPageRoutingModule } from './weather-data-routing.module';
import { WeatherDataPage } from './weather-data.page';
#NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
WeatherDataPageRoutingModule
],
declarations: [WeatherDataPage]
})
export class WeatherDataPageModule {
weather;
constructor(private weatherdataservice: WeatherDataService){}
ngOnInit(){
this.weatherdataservice.getWeather().subscribe((data)=>{
console.log(data);
this.weather = data['weather'];
}
)
}
}
this is the code for the data.module.ts file
import { Injectable } from '#angular/core';
import { HttpClient} from '#angular/common/http'
#Injectable({
providedIn: 'root'
})
export class WeatherDataService {
APIKey = 'fec30507acb533f670080ab3174f226f';
constructor(private httpClient: HttpClient) { }
public getWeather(){
return this.httpClient.get('api.openweathermap.org/data/2.5/weather?lat={53.87}&lon={8.63}&appid={fec30507acb533f670080ab3174f226f}')
}
}
this is the code for the data.services ts file.
From below code, seems like you wanted to redirect to some page though you have response from the api. Instead of link redirection, try to create new page and pass response.
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>
Weather Ireland
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Weather Ireland</ion-title>
</ion-toolbar>
</ion-header>
**<a class="button icon-right ion-plus-round" href="../weather-data/weather-data.page.html">weatherData</a>**
</ion-content>
In WeatherDataPage try using NavController
declare, navCtrl: NavController in constructor and use this.navCtrl.push(component_name, {whetherData: this.weather});
And after navigating to new component page use, NavParams. Declare navParams: NavParams and use navParams.get("whetherData");
I am following the tutorial here: https://coursetro.com/posts/code/154/Angular-6-Tutorial---Learn-Angular-6-in-this-Crash-Course
I currently have the code up to the section titled Fetching More Data from the API working. In short this is supposed to make a page with a bunch of users accessed through a toy API. The users are listed on a page with some personal information, and each one links to a very basic profile page displaying their details. Up to the section I mentioned above, I am successfully interfacing with the API, getting the users and displaying them and some personal information on the main page.
However, the code in this section is intended to collect an individual user's details and display them on a linked page. In trying to follow the example, my code does produce a page with the right outlines, but the value of the variable user$ and its fields like user$.name don't seem to be loaded by the details component. Where those values are supposed to show up, it's blank.
The app files:
app-routing.module.ts
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { PostsComponent } from './posts/posts.component';
const routes: Routes = [
{
path: '',
component: UsersComponent
},
{
path: 'details/:id',
component: DetailsComponent
},
{
path: 'posts',
component: PostsComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
app.component.html
<div id="container">
<app-sidebar></app-sidebar>
<div id="content">
<router-outlet></router-outlet>
</div>
</div>
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SidebarComponent } from './sidebar/sidebar.component';
import { PostsComponent } from './posts/posts.component';
import { UsersComponent } from './users/users.component';
import { DetailsComponent } from './details/details.component';
import { HttpClientModule } from '#angular/common/http';
#NgModule({
declarations: [
AppComponent,
SidebarComponent,
PostsComponent,
UsersComponent,
DetailsComponent
],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import {HttpClient } from '#angular/common/http';
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getUsers() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
getUser(userId) {
return this.http.get('https://jsonplaceholder.typicode.com/users'+userId)
}
getPosts() {
return this.http.get('https://jsonplaceholder.typicode.com/posts')
}
}
users files:
users.component.html
<h1>Users</h1>
<ul>
<li *ngFor="let user of users$">
{{user.name}}
<ul>
<li>{{user.email}}</li>
<li>{{user.website}}</li>
</ul>
</li>
</ul>
users.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
#Component({
selector: 'app-users',
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {
users$: Object;
constructor(private data: DataService) { }
ngOnInit() {
this.data.getUsers().subscribe(
data => this.users$ = data
);
}
}
details files:
details.component.html
<h1>{{ user$.name }}</h1>
<ul>
<li><strong>Username: </strong> {{user$.username}}</li>
<li><strong>Email: </strong> {{user$.email}}</li>
<li><strong>Phone: </strong> {{user$.phone}}</li>
</ul>
details.component.ts
import { Component, OnInit } from '#angular/core';
import { DataService } from '../data.service';
import { Observable } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-details',
templateUrl: './details.component.html',
styleUrls: ['./details.component.scss']
})
export class DetailsComponent implements OnInit {
user$: Object;
constructor(private data: DataService, private route: ActivatedRoute) {
this.route.params.subscribe( params => this.user$ = params.id );
console.log(this.route.params);
}
ngOnInit() {
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
);
}
}
I tried logging values to the console, but I don't fully understand how TypeScript works so I don't fully know what I really should expect from these logs. In any case, in the log that I made in the details TypeScript file, it showed an object with no apparent loading errors.
this.route.params is a Observable. I am not sure what you can get by logging it.
I would suggest you add a log when subscribing to a observable and see what kind of data you really get. Like.
this.data.getUser(this.user$).subscribe(
data => {console.log(data);this.user$ = data}
);
#Adem, As Haijin comment, you must "work" a bit in subscribe parameter. The idea is that you subscribe to get the parameter, and, when you have the parameter, you ask about the user. But you need to make in the same step using switchMap
ngOnInit()
{
//You subscribe the param. When you have ask for the user
this.route.params.subscribe( params =>
{
this.user$ = params.id;
//In subscribe you ask for the user
this.data.getUser(this.user$).subscribe(
data => this.user$ = data
)
});
}
Well, really In Angular is better don't subscribe two times else using Rjxs and switchMap
ngOnInit()
{
//You subscribe the params, but you don't want the param
this.route.params.pipe(
switchMap(params =>
{ //you want return the user
return this.data.getUser(params.id)
})
).subscribe(data => this.user$ = data)
}
I'm trying to send data from my home.ts file to the app.component.ts file using EventEmitter and Output. But everytime I reference the home page component in my app.html I get this seemingly random error. When I remove NavController from the constructor in home.ts, the error goes away.
home.ts :
import { Component, EventEmitter, Output } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html',
})
export class HomePage {
message : any;
#Output() notify : EventEmitter<Object> = new EventEmitter<Object>();
constructor(public navCtrl: NavController) {
}
ionViewDidLoad(){
this.message = {"Name":"Sid", "Age":17};
this.notify.emit(this.message);
}
}
app.html :
<ion-nav [root]="rootPage"></ion-nav>
<page-home (notify)="getChildData($event)"></page-home>
app.component.ts :
import { Component, ViewChild, ViewChildren } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { HomePage } from '../pages/home/home';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = HomePage;
constructor(platform: Platform, statusBar: StatusBar, splashScreen:
SplashScreen) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
});
}
getChildData(message){
console.log(message["Name"]);
console.log(message["Age"]);
}
}
How do I fix this error ? I need to use the NavController so I can't remove it. I want to still be able to send data from the child component to the parent component
The error is pointing out that you should provide the NavController in the providers section somewhere. This section could be in several modules of your application but the general one is the app.module.ts file.
In there you have a providers section in which you can provide services or providers for the Angular dependency injection mechanism to work appropriately.
So my first thougth would be to add the navController in the providers section of your app.module.ts file. This ensures that Angular can resolve the dependency to your NavController. Putting it in the app.module.ts file makes it having the same instance fo your navcontroller all over your application.
#NgModule({
bootstrap: [ AppComponent ],
declarations: [
...
],
imports: [
...
],
exports: [
],
providers: [
...
NavController
]
})
However, since you are using ionic, I would check out a related topic on the following url.
Ionic 2 - Runtime Error No provider for NavController
I have found this open source icon package which I installed in my project featherIcons, and is listed inside my_modules directory. However Im trying to use it but I just cant seem to make it work.
The issue is, I think I have to be somehow importing the package but not sure how or where.
app-component.html
<div class="navbar__nav-container">
<ul class="navbar__nav-container__nav-items">
<li>Platform</li>
<li>Stix/Taxi</li>
<li>Menu</li>
<li>
<i data-feather="circle"></i>
</li>
</ul>
</div>
app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { RoutingModule } from './routing.module';
import { SharedModule } from './shared/shared.module';
import { CatService } from './services/cat.service';
import { UserService } from './services/user.service';
import { AuthService } from './services/auth.service';
import { AuthGuardLogin } from './services/auth-guard-login.service';
import { AuthGuardAdmin } from './services/auth-guard-admin.service';
import { AppComponent } from './app.component';
import { CatsComponent } from './cats/cats.component';
import { AboutComponent } from './about/about.component';
import { RegisterComponent } from './register/register.component';
import { LoginComponent } from './login/login.component';
import { LogoutComponent } from './logout/logout.component';
import { AccountComponent } from './account/account.component';
import { AdminComponent } from './admin/admin.component';
import { NotFoundComponent } from './not-found/not-found.component';
#NgModule({
declarations: [
AppComponent,
CatsComponent,
AboutComponent,
RegisterComponent,
LoginComponent,
LogoutComponent,
AccountComponent,
AdminComponent,
NotFoundComponent
],
imports: [
RoutingModule,
SharedModule
],
providers: [
AuthService,
AuthGuardLogin,
AuthGuardAdmin,
CatService,
UserService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent]
})
export class AppModule { }
Any help would be appreciated
Nevermind, I figured the solution, and I'll post the solution here so that it can help the rest.
So as the library states in the link provided, I had to install it like so
npm install feather-icons --save - the --save is very important because it will be referenced in my package.json. Once installed, you will be able to see it in node_modules directory.
Then in which ever component I want to use the library, all I had to do is import it the following way:
Since I wanted to use an icon from the library in app.component.ts:
app.component.ts
import {Component, OnInit} from '#angular/core';
import { AuthService } from './services/auth.service';
/*
- feather-icons is a directory installed in node_modules.
- I dont have to specify the whole path like '../node_modules/path/to/feather-icons'.
- Also rememeber to call the feather.replace() inside ngOnInit
- because it needs to first make sure the component loads first
*/
import * as feather from 'feather-icons';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
constructor (
public auth: AuthService
) { }
ngOnInit() {
feather.replace();
}
}
Then in my app.component.html:
<div class="navbar__nav-container">
<ul class="navbar__nav-container__nav-items">
<li>Platform</li>
<li>Stix/Taxi</li>
<li>Menu</li>
<li>
<i data-feather="circle"></i>
</li>
</ul>
</div>
This was all to it to be honest.
Hope this helps :)
Solution using angular-feather
The advantage of it being that you cherry pick only the icons that you need, thus reducing bundle size.
Install the package
npm install angular-feather
Import the icons you need
Import the icons a la carte in the angular module of your needs
import { NgModule } from '#angular/core';
import { FeatherModule } from 'angular-feather';
import { Camera, Heart, Github } from 'angular-feather/icons';
// Select some icons (use an object, not an array)
const icons = {
Camera,
Heart,
Github
};
#NgModule({
imports: [
FeatherModule.pick(icons)
],
exports: [
FeatherModule
]
})
export class IconsModule {}
Import IconsModule and use component
<i-feather name="heart"></i-feather>
<i-feather name="camera"></i-feather>
Stackblitz demo
I am currently using Angular2 for my application and now I want to add ng2-table to my component.
ng2-Table on Git
I am getting this error and couldn't help but ask:
angular2-polyfills.js:487 Unhandled Promise rejection: Template parse errors:
Can't bind to 'colums' since it isn't a known property of 'ng-table'.
1. If 'ng-table' is an Angular component and it has 'colums' input, then
verify that it is part of this module.
2. If 'ng-table' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA"
to the '#NgModule.schema' of this component to suppress this message.
("
</div>-->
<ng-table [ERROR ->][colums]="columns" [rows]="rows" > </ng-table>
<div class="">
"): DeviceOverviewComponent#18:10 ;
Zone: <root> ; Task: Promise.then ; Value: Error: Template parse errors:(…)
In my html I got this:
<ng-table [columns]="columns" [rows]="rows" > </ng-table>
My Component is this:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { DeviceService } from '../services/device.service';
#Component({
selector: 'device-overview',
templateUrl: 'dist/html/deviceoverview.component.html',
providers: [DeviceService],
})
export class DeviceOverviewComponent {
devices: any;
columns: any;
rows: any;
constructor(private deviceService: DeviceService, private router: Router) {
}
loadDevices() {
this.deviceService.getDevices()
.then((data) => {
this.devices = data
this.rows = this.devices
})
}
goToDevice(deviceName: string) {
this.router.navigateByUrl('/devices/' + deviceName)
}
ngOnInit() {
this.columns = [
{ title: "test", name: "id" }]
this.loadDevices();
}
}
And my app.module is this:
import { NgModule } from '#angular/core';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { Ng2TableModule } from 'ng2-table/ng2-table';
import { AppComponent } from './components/app.component';
import { DeviceOverviewComponent } from './components/deviceoverview.component'
import { DeviceService } from './services/device.service';
import { routing } from './app.routing';
#NgModule({
imports: [
Ng2TableModule,
BrowserModule,
FormsModule,
HttpModule,
routing,
],
declarations: [
DeviceOverviewComponent,
AppComponent,
],
providers:
[
{provide: LocationStrategy, useClass: HashLocationStrategy},
DeviceService,
],
bootstrap: [AppComponent]
})
export class AppModule { }
Does anybody know anything about the Usage of ng2-table? Or is there a valid alternative, since the demo page/usage documentation is not available by now?
I found some alternatives, but lots of them had their last commit a long time ago, which might be a problem, since I am always using latest Angular2.
Thanks for reading and any hel is appreciated!
EDIT:
I've made it to the next step!
I needed to add
import {CUSTOM_ELEMENTS_SCHEMA} from '#angular/core'
#NgModule({ ...,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
within my app.module.ts
Now I am getting the table header with the "test" column and the ID property of my row data is displayed correctly.
Even the demo from ng2-table didn't have that import.
I guess docs and demos arent made for newbes nowadays. :/
i see a typo in your html:
[colums]="columns"
It should be
[columns]="columns"
You're missing n
Plunker Example (I also tried it on local machine and it works)
You shouldn't use CUSTOM_ELEMENTS_SCHEMA
systemjs.config.js
map: {
...
'ng2-table': 'npm:ng2-table'
},
packages: {
...
'ng2-table': {
defaultExtension: 'js'
}
}
After long time I close this issue.
In my case I have these structure:
src
--app
-- app.module
-- TravelPlan
-- travel-plan.module
-- test.component
So, I was trying put the ng2-smart-table in app.module, but I was wrong. The correct is put in travel-plan.module.