Build a Basic Note App with Flutter and GetX (CRUD Operations Explained Step-by-Step

adnan minhanadnan minhan
4 min read

✨ Introduction

In this tutorial, we'll build a simple Note app using Flutter and GetX, one of the most lightweight and powerful state management packages in the Flutter ecosystem.

You will learn how to:

  • Create a model class

  • Implement a controller with GetX

  • Add, read, update, and delete notes (CRUD operations)

  • Navigate between views using GetX

  • Build a responsive and clean UI

Perfect for beginners who want to understand basic app architecture and GetX!


πŸ“ Project Structure

/lib
  └── NoteApp
        β”œβ”€β”€ model
        β”‚     └── note_model.dart
        β”œβ”€β”€ controllers
        β”‚     └── note_controller.dart
        β”œβ”€β”€ views
        β”‚     β”œβ”€β”€ add_note_form.dart
        β”‚     β”œβ”€β”€ edit_note_view.dart
        β”‚     └── note_home_view.dart
        └── main.dart

🧱 Step 1: Creating the Note Model

This class will store each note's data.

class NoteModel {
  final int id;
  final String title;
  final String description;

  NoteModel(this.id, this.title, this.description);
}

🧠 What This Does:

This defines a NoteModel class that represents a single note in your app. Each note contains:

  1. An ID (int) – a unique identifier for the note.

  2. A Title (String) – the heading or short label of the note.

  3. A Description (String) – the detailed content of the note.

FieldTypePurpose
idintUniquely identifies each note.
titleStringThe note’s title or heading.
descriptionStringThe content/details of the note.

🎯 Step 2: Setting Up the Note Controller with GetX

The controller manages the state and logic of the app.

import 'package:allapipractice/NoteApp/model/note_model.dart';
import 'package:flutter/material.dart';
import 'package:get/state_manager.dart';

class NoteController extends GetxController {
  final titleController = TextEditingController();
  final descriptionController = TextEditingController();
  final noteList = <NoteModel>[].obs;

  addNewNote(NoteModel noteData) {
    noteList.add(noteData);
    titleController.clear();
    descriptionController.clear();
    update();
  }

  deleteNote(int index) {
    noteList.removeAt(index);
    update();
  }

  updateNote(int index, NoteModel updatedNote) {
    noteList[index] = updatedNote;
    titleController.clear();
    descriptionController.clear();
    update();
  }
}

Here, we use RxList to make noteList observable and clear the text controllers after each action.


🏑 Step 3: Home Screen - Listing the Notes

import 'package:allapipractice/NoteApp/controllers/note_controller.dart';
import 'package:allapipractice/NoteApp/views/add_note_form.dart';
import 'package:allapipractice/NoteApp/views/edit_note_view.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class NoteHomeView extends StatelessWidget {
  final controller = Get.put(NoteController());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("My Notes"),
        centerTitle: true,
      ),
      body: Obx(
        () => ListView.builder(
          padding: const EdgeInsets.all(16),
          itemCount: controller.noteList.length,
          itemBuilder: (context, index) {
            final singleNote = controller.noteList[index];
            return Card(
              margin: const EdgeInsets.only(bottom: 12),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(12),
              ),
              elevation: 2,
              child: ListTile(
                  title: Text(
                    singleNote.title,
                    style: const TextStyle(fontSize: 16),
                  ),
                  subtitle: Text(
                    singleNote.description,
                    style: const TextStyle(fontSize: 12),
                  ),
                  leading: const Icon(Icons.note),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                          onPressed: () {
                            Get.to(() => EditNote(
                                  index: index,
                                  note: singleNote,
                                ));
                          },
                          icon: Icon(Icons.edit)),
                      IconButton(
                          onPressed: () {
                            Get.snackbar("Deleted",
                                "${singleNote.title} has been deleted");
                            controller.deleteNote(index);
                          },
                          icon: Icon(Icons.delete))
                    ],
                  )),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Get.to(() => AddNoteForm());
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}

βž• Step 4: Add Note View

import 'package:allapipractice/NoteApp/model/note_model.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../controllers/note_controller.dart';

class AddNoteForm extends StatelessWidget {
  final controller = Get.find<NoteController>();
  AddNoteForm({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Add New Note"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: controller.titleController,
              decoration: InputDecoration(labelText: 'Title'),
            ),
            TextField(
              controller: controller.descriptionController,
              decoration: InputDecoration(labelText: 'Description'),
            ),
            SizedBox(height: 16),
            ElevatedButton(
                onPressed: () {
                  controller.addNewNote(NoteModel(
                      controller.noteList.length + 1,
                      controller.titleController.text,
                      controller.descriptionController.text));
                  Get.snackbar("Success", "Note has been created");
                  Get.back();
                },
                child: Text("Save Note"))
          ],
        ),
      ),
    );
  }
}

✏️ Step 5: Edit Note View

import 'package:allapipractice/NoteApp/model/note_model.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

import '../controllers/note_controller.dart';

class EditNote extends StatelessWidget {
  final NoteModel note;
  final int index;

  final NoteController controller = Get.find();
  EditNote({Key? key, required this.note, required this.index})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    controller.titleController.text = note.title;
    controller.descriptionController.text = note.description;
    return Scaffold(
      appBar: AppBar(
        title: Text("Edit Note"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: controller.titleController,
              decoration: InputDecoration(labelText: 'Title'),
            ),
            TextField(
              controller: controller.descriptionController,
              decoration: InputDecoration(labelText: 'Description'),
            ),
            SizedBox(height: 16),
            ElevatedButton(
                onPressed: () {
                  final updatedNote = NoteModel(
                      note.id,
                      controller.titleController.text,
                      controller.descriptionController.text);
                  controller.updateNote(index, updatedNote);
                  Get.snackbar("Success", "Note updated successfully");
                  Get.back();
                },
                child: Text("Save Note"))
          ],
        ),
      ),
    );
  }
}

πŸ§ͺ Final Testing

  • Run your app.

  • Try adding, editing, and deleting notes.

  • Make sure data updates correctly in real time.


🧹 Improvements You Can Try

  • Store notes in local database (Hive or Sqflite)

  • Add input validation

  • Support dark mode and theming

  • Add tags or categories


βœ… Conclusion

You now have a fully functional Note app with CRUD operations using Flutter and GetX!

If you're new to state management, this is a perfect first step before moving on to persistent storage, APIs, and more advanced app architecture.

Happy coding! πŸš€

0
Subscribe to my newsletter

Read articles from adnan minhan directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

adnan minhan
adnan minhan