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 { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
import { CKEditorModule } from '@ckeditor/ckeditor5-angular';
@NgModule({
declarations: [AppComponent],
entryComponents: [],
imports: [
BrowserModule,
IonicModule.forRoot(),
AppRoutingModule,
HttpClientModule,
CKEditorModule
],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent],
})
export class AppModule {}
app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{
path: '',
redirectTo: 'home',
pathMatch: 'full'
},
{
path: 'detail',
loadChildren: () => import('./modals/detail/detail.module').then( m => m.DetailPageModule)
},
{
path: 'home',
loadChildren: () => import('./pages/home/home.module').then( m => m.HomePageModule)
},
{
path: 'form-note',
loadChildren: () => import('./modals/form-note/form-note.module').then( m => m.FormNotePageModule)
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule { }
note.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
@Injectable({
providedIn: 'root'
})
export class NoteService {
server:string = "http://localhost/api/";
constructor(
public http: HttpClient
) { }
getListNote(){
return this.http.get(this.server+'note/');
}
getDetailNote(noteId){
return this.http.get(this.server+'note/'+noteId);
}
addNote(noteTitle,noteContent){
return this.http.post(this.server+'note/',{
note_title:noteTitle,
note_content:noteContent
});
}
editNote(noteId,noteTitle,noteContent){
return this.http.put(this.server+'note/'+noteId,{
note_title:noteTitle,
note_content:noteContent
});
}
deleteNote(noteId){
return this.http.delete(this.server+'note/'+noteId);
}
}
home.page.html
<ion-header>
<ion-toolbar color="primary">
<ion-title>Catatan</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button (click)="modalFormNote()">
<ion-icon name="add-outline"></ion-icon>
</ion-fab-button>
</ion-fab>
<ion-list>
<ion-item-sliding *ngFor="let item of listsNote;let i = index">
<ion-item lines="full" (click)="modalDetail(i)">
<ion-label>{{item.note_title}}</ion-label>
</ion-item>
<ion-item-options side="end">
<ion-item-option color="primary" (click)="modalFormNote(i)">Edit</ion-item-option>
<ion-item-option color="danger" (click)="deleteNote(i)">Delete</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
</ion-content>
home.page.ts
import { Component, OnInit } from '@angular/core';
import { NoteService } from '../../services/note.service';
import { ToastController, ModalController, AlertController, LoadingController } from '@ionic/angular';
import { DetailPage } from '../../modals/detail/detail.page';
import { FormNotePage } from '../../modals/form-note/form-note.page';
@Component({
selector: 'app-home',
templateUrl: './home.page.html',
styleUrls: ['./home.page.scss'],
})
export class HomePage implements OnInit {
listsNote:any;
constructor(
private noteService:NoteService,
public toastCtrl:ToastController,
public modalCtrl:ModalController,
public alertCtrl:AlertController,
public loadCtrl:LoadingController
) { }
ngOnInit() {
}
ionViewWillEnter(){
// MEMANGGIL API LIST NOTE
this.noteService.getListNote().subscribe(
res => {
if(res["result"]=="success"){ // JIKA HASIL SUCCESS
this.listsNote = res["data"];
}else{ // JIKA HASIL ERROR
this.presentToast(res["message"]);
}
},
err => {
console.log(err.error)
}
)
}
// FUNCTION MODAL DETAIL
async modalDetail(i){
const modal = await this.modalCtrl.create({
component:DetailPage,
componentProps:{
dataNote:this.listsNote[i]
}
});
return await modal.present();
}
// FUNCTION MODAL TAMBAH NOTE
async modalFormNote(i=null){
let data = i==null ? null : this.listsNote[i];
const modal = await this.modalCtrl.create({
component:FormNotePage,
componentProps:{
dataNote:data
}
});
// KETIKA MODAL DI TUTUP
modal.onWillDismiss().then(dataReturned => {
if(dataReturned.role=="add"){ // JIKA DIDAPAT DARI ADD DATA
this.listsNote.unshift(dataReturned.data);
}else if(dataReturned.role=="edit"){ // JIKA DIDAPAT DARI EDIT DATA
this.listsNote[i] = dataReturned.data
}
});
return await modal.present();
}
// FUNCTION CONFIRM DELETE NOTE
async deleteNote(i){
// MEMBUAT ALERT PROMPT
const alert = await this.alertCtrl.create({
header: 'Delete',
message: 'Hapus Catatan ?',
buttons: [
{
text:"Tidak"
},
{
text:"Iya",
role:"iya"
}
]
});
// RUNNING ALERT
await alert.present();
// SETELAH ALERT DITUTUP
await alert.onDidDismiss().then(res => {
if(res.role=="iya"){ // JIKA BUTTON YANG DITEKAN = "IYA"
this.prosesDelete(i);
}
});
}
// FUNCTION ACTION DELETE NOTE
async prosesDelete(i){
// MEMBUAT LOADING
const loading = await this.loadCtrl.create({
message: 'Please wait'
});
// TAMPILKAN LOADING
await loading.present();
// MENGIRIM ID NOTE YANG INGIN DIHAPUS KE API
await this.noteService.deleteNote(this.listsNote[i]["note_id"]).subscribe(
res => {
if(res["result"]=="success"){ // JIKA HASIL KE API SUCCESS
this.listsNote.splice(i,1); // HAPUS DATA NOTE DARI ARRAY
}
// TAMPILKAN PESAN
this.presentToast(res["message"]);
// SEMBUNYIKAN LOADING
loading.dismiss();
},
err => {
console.log(err.error)
// SEMBUNYIKAN LOADING
loading.dismiss();
}
);
}
//FUNCTION PRESENT TOAST
async presentToast(a){
const toast = await this.toastCtrl.create({
message: a,
duration: 1500
});
toast.present();
}
}
detail.page.html
<ion-header>
<ion-toolbar color="primary">
<ion-title>{{dataNote.note_title}}</ion-title>
<ion-buttons slot="end" (click)="closeModal()">
<ion-button>
<ion-icon name="close-outline"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-card>
<ion-card-content>
<div [innerHTML]="dataNote.note_content"></div>
</ion-card-content>
</ion-card>
</ion-content>
detail.page.ts
import { Component, OnInit, Input } from '@angular/core';
import { ModalController } from '@ionic/angular';
@Component({
selector: 'app-detail',
templateUrl: './detail.page.html',
styleUrls: ['./detail.page.scss'],
})
export class DetailPage implements OnInit {
@Input() public dataNote:any;
constructor(
public modalCtrl:ModalController
) { }
ngOnInit() {
}
//Tutup Modal
async closeModal(data){
await this.modalCtrl.dismiss(data);
}
}
form-note.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { FormNotePageRoutingModule } from './form-note-routing.module';
import { FormNotePage } from './form-note.page';
import { CKEditorModule } from '@ckeditor/ckeditor5-angular';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
FormNotePageRoutingModule,
CKEditorModule,
],
declarations: [FormNotePage]
})
export class FormNotePageModule {}
form-note.page.html
<ion-header>
<ion-toolbar color="primary">
<ion-title>Catatan</ion-title>
<ion-buttons slot="end" (click)="closeModal(null)">
<ion-button>
<ion-icon name="close-outline"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content padding>
<ion-input type="text" [(ngModel)]="noteId" style="display: none;"></ion-input>
<ion-card>
<ion-card-content>
<ion-item-group>
<ion-label>Title</ion-label>
<ion-input type='text' [(ngModel)]="noteTitle"></ion-input>
</ion-item-group>
<ion-item-group>
<ion-label>Content</ion-label>
<ckeditor [editor]="Editor" [(ngModel)]="noteContent" style="height: 500px;" [config]="{toolbar : ['heading','|','bold', 'italic','underline','|','NumberedList','BulletedList','Blockquote']}"></ckeditor>
</ion-item-group>
<ion-button expand="block" color="primary" (click)="saveNote()" *ngIf="noteId==''">
Save
</ion-button>
<ion-button expand="block" color="primary" (click)="updateNote(noteId)" *ngIf="noteId!=''">
Update
</ion-button>
</ion-card-content>
</ion-card>
</ion-content>
form-note.page.ts
import { Component, OnInit, Input } from '@angular/core';
import { ModalController, ToastController, LoadingController } from '@ionic/angular';
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import { NoteService } from '../../services/note.service';
@Component({
selector: 'app-form-note',
templateUrl: './form-note.page.html',
styleUrls: ['./form-note.page.scss'],
})
export class FormNotePage implements OnInit {
@Input() public dataNote:any;
noteId:any;
noteTitle:string = "";
noteContent:any;
public Editor = ClassicEditor;
constructor(
public modalCtrl:ModalController,
private noteService:NoteService,
public toastCtrl:ToastController,
public loadCtrl:LoadingController
) { }
ngOnInit() {
}
ionViewWillEnter(){
if(this.dataNote===null){
this.noteId = "";
}else{
this.noteId = this.dataNote.note_id;
this.noteTitle = this.dataNote.note_title;
this.noteContent = this.dataNote.note_content;
}
console.log(this.noteId);
}
// MENYIMPNAN FORM NOTE
async saveNote(){
const loading = await this.loadCtrl.create({
message: 'Please wait'
});
await loading.present();
await this.noteService.addNote(this.noteTitle,this.noteContent
).subscribe(
res => {
console.log(res);
if(res["result"]=="success"){
this.closeModal({
note_id:res["data"]["note_id"],
note_title:this.noteTitle,
note_content:this.noteContent
},"add")
}
this.presentToast(res["message"]);
loading.dismiss();
},
err => {
console.log(err);
loading.dismiss();
}
);
}
// MERUBAH FORM NOTE
async updateNote(noteId){
const loading = await this.loadCtrl.create({
message: 'Please wait'
});
await loading.present();
await this.noteService.editNote(noteId,this.noteTitle,this.noteContent
).subscribe(
res => {
console.log(res);
if(res["result"]=="success"){
this.closeModal({
note_id:this.noteId,
note_title:this.noteTitle,
note_content:this.noteContent
},"edit")
}
this.presentToast(res["message"]);
loading.dismiss();
},
err => {
console.log(err);
loading.dismiss();
}
);
}
async presentToast(a){
const toast = await this.toastCtrl.create({
message: a,
duration: 1500
});
toast.present();
}
//Tutup Modal
async closeModal(data=null,role=null){
await this.modalCtrl.dismiss(data,role);
}
}