Issue
I am learning how to build an app in ionic so I am very much a beginner to the language. My current project is a shopping list app, which should allow the user to add and remove items as well as edit them. Currently I am in the beginning stages. Things were going well until I tried to clean up the code by separating it out and adding services. I was able to add, remove, and edit items as planned and everything displayed as it was meant to. Now the app loads, and the tabs at the bottom load, but none of the content of any of the actual tabs loads.
I was expecting the tabs to load as they were before the split. I've tried rewatching the videos for my class, but they are 9 years old and not very helpful. As far as I can tell I have the required elements in place, but I can only assume I've deleted something important by mistake when I was cleaning it up. However studying both those videos and newer ones as well as apps on GitHub have not shown me where I went wrong.
The only pages I have made any changes to are as follows:
tab1.page.ts
import { Component } from '@angular/core';
import { GroceriesServiceService } from '../groceries-service.service';
@Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
title = "Grocery List";
constructor(public groceriesService: GroceriesServiceService) {}
loadItems(){
return this.groceriesService.getItems();
}
removeItem(item, index){
this.groceriesService.inputDialogService.presentToast('bottom', item);
this.groceriesService.removeItem(index);
}
editItem(item, index) {
this.groceriesService.inputDialogService.promptAlert(item, index);
this.groceriesService.editItem(item, index);
}
addItem() {
this.groceriesService.inputDialogService.promptAlert();
}
}
tab1.page.html
<ion-header>
<ion-toolbar>
<ion-title>
<h2>{{title}}</h2>
</ion-title>
</ion-toolbar>
</ion-header>
<ion-fab slot="fixed" vertical="top" horizontal="end">
<ion-fab-button (click)="addItem()">
<ion-icon name="add"></ion-icon>
</ion-fab-button>
</ion-fab>
<ion-content padding>
<h3 text-center *ngIf="loadItems().length === 0">
No items listed.
</h3>
<ion-list>
<ion-item-sliding *ngFor="let item of loadItems(); let i = index">
<ion-item>
<div>
<h5>{{item.name}}</h5>
<p>{{item.quantity}}</p>
</div>
</ion-item>
<ion-item-options>
<ion-item-option color="success" (click)="editItem(item,i)">
<ion-icon name="pencil"></ion-icon>
<div>
<p>Edit</p>
</div>
</ion-item-option>
<ion-item-option color="danger" (click)="removeItem(item, i)">
<ion-icon name="trash"></ion-icon>
<div>
<p>Delete</p>
</div>
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
</ion-content>
tabs.page.html
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="tab1">
<ion-icon aria-hidden="true" name="basket-outline"></ion-icon>
<ion-label>Home</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab2">
<ion-icon aria-hidden="true" name="book-outline"></ion-icon>
<ion-label>About</ion-label>
</ion-tab-button>
<ion-tab-button tab="tab3">
<ion-icon aria-hidden="true" name="people-outline"></ion-icon>
<ion-label>Contacts</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
groceries-service.ts
import { InputDialogService } from './input-dialog.service';
export class GroceriesServiceService {
items = [];
constructor(public inputDialogService: InputDialogService) {
}
getItems(){
return this.items;
}
removeItem(index){
this.items.splice(index, 1);
}
editItem(item, index){
this.items[index] = item;
}
addItem(item){
this.items.push(item);
}
}
input-dialog-service.ts
import { Injectable } from '@angular/core';
import { ToastController } from '@ionic/angular';
import { AlertController } from '@ionic/angular';
import { GroceriesServiceService } from './groceries-service.service';
@Injectable({
providedIn: 'root'
})
export class InputDialogService {
handlerMessage = '';
roleMessage = '';
async presentToast(position: 'top' | 'middle' | 'bottom', item) {
const toast = await this.toastController.create({
message: "Removing item - " + item.name ,
duration: 1500,
position: position
});
await toast.present();
}
async promptAlert(item?, index?) {
const alert = await this.alertController.create({
header: 'Please enter the item information',
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: data => {
this.handlerMessage = 'Alert canceled';
},
},
{
text: 'Add',
role: 'confirm',
handler: data => {
this.handlerMessage = 'Alert confirmed';
console.log("Item added: " + data.name);
if(index != undefined) {
this.groceriesService.editItem(item, index);
}
else {
this.groceriesService.addItem(data);
}
},
},
],
inputs: [
{
name: 'name',
placeholder: 'Name',
value: item ? item.name : null
},
{
name: 'quantity',
type: 'number',
placeholder: 'Quantity',
value: item ? item.quantity : null
}
],
});
await alert.present();
}
constructor(private toastController: ToastController, private alertController: AlertController, public groceriesService: GroceriesServiceService) {
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Groceries App</title>
<base href="/" />
<meta name="color-scheme" content="light dark" />
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<link rel="icon" type="image/png" href="assets/icon/favicon.png" />
<!-- add to homescreen for ios -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
</head>
<body>
<app-root></app-root>
</body>
</html>
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { GroceriesServiceService } from './groceries-service.service';
import { InputDialogService } from './input-dialog.service';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent],
})
export class AppModule {}
Solution
You don't need to import service in groceries because it will create circular dependency injection error.
Also you forgot to add Injectable
decorator in you groceries service.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class GroceriesServiceService {
items: any = [];
constructor() {
}
getItems() {
return this.items;
}
removeItem(index: any) {
this.items.splice(index, 1);
}
editItem(item: any, index: any) {
this.items[index] = item;
}
addItem(item: any) {
this.items.push(item);
}
}
Also in your tab, you are calling the service methods incorrectly.
import { Component } from '@angular/core';
import { GroceriesServiceService } from '../groceries-service.service';
import { InputDialogService } from '../input-dialog.service';
@Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss'],
})
export class Tab1Page {
title = "Grocery List";
constructor(public groceriesService: GroceriesServiceService, private inputDialogService: InputDialogService) { }
loadItems() {
return this.groceriesService.getItems();
}
removeItem(item, index) {
this.inputDialogService.presentToast('bottom', item);
this.groceriesService.removeItem(index);
}
editItem(item, index) {
this.inputDialogService.promptAlert(item, index);
this.groceriesService.editItem(item, index);
}
addItem() {
this.inputDialogService.promptAlert();
}
}
Answered By - slashsharp
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.