flutter getx - deal with rest api (get, post, put, delete)
Tags: flutter, getx, restapi
Published: 2023-05-26 13:38:09

## Overview
- Step 1: Make server
- Step 2: Make request to server

## Prerequisites
- NodeJS
- Baseknowledge about Flutter and Getx

## Step 1: Make server
### 1.1. Install json-server
Ref: https://github.com/typicode/json-server
```bash
npm install -g json-server
```

### 1.2. Make data
```json
// data.json
{
  "students": [
    {
      "id": "1",
      "name": "John Doe",
      "email": "johndoe@gmail.com"
    },
  ]
}
```

### 1.3. Run rest server with this file
```bash
json-server --watch data.json

## result
  \{^_^}/ hi!

  Loading data.json
  Done

  Resources
  http://localhost:3000/students

  Home
  http://localhost:3000

  Type s + enter at any time to create a snapshot of the database
  Watching...

```

### 1.4. Verify that everything working correct
```bash
curl http://localhost:3000/students

# result
[
    {
      "id": "1",
      "name": "John Doe",
      "email": "johndoe@gmail.com"
    },
]
```

## Step 2: Make request to server using Getx
Ref: https://pub.dev/packages/get

### 2.1. Make file main.dart
```dart
// main.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';

Future<void> main() async {
  Get.put(StudentProvider());

  runApp(GetMaterialApp(home: Home()));
}

class Home extends StatelessWidget {
  final StudentController studentController = Get.put(StudentController());
  Home({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Rest API"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () {
                studentController.getAllStudent();
              },
              child: const Text("GetAllStudent"),
            ),
            ElevatedButton(
              onPressed: () {
                studentController.getStudentById("1");
              },
              child: const Text("GetStudentById"),
            ),
            ElevatedButton(
              onPressed: () {
                var uniqueId =
                    new DateTime.now().millisecondsSinceEpoch.toString();
                studentController.createStudent(
                  Student(
                    id: uniqueId,
                    name: "John Doe $uniqueId",
                    email: "test$uniqueId@gmail.com",
                  ),
                );
              },
              child: const Text("CreateStudent"),
            ),
            ElevatedButton(
              onPressed: () {},
              child: const Text("UpdateStudent"),
            ),
            ElevatedButton(
              onPressed: () {},
              child: const Text("RemoveStudent"),
            ),
          ],
        ),
      ),
    );
  }
}

class StudentController extends GetxController {
  final studentsLoading = false.obs;

  final StudentProvider studentProvider = Get.find();

  @override
  Future<void> onInit() async {
    super.onInit();
    await getAllStudent();
  }

  Future<void> getAllStudent() async {
    studentsLoading.value = true;
    try {
      var response = await studentProvider.getAll();
      print(response.body);
    } finally {
      studentsLoading.value = false;
    }
  }

  Future<void> getStudentById(String id) async {
    studentsLoading.value = true;
    try {
      var response = await studentProvider.getById(id);
      print(response.body);
    } finally {
      studentsLoading.value = false;
    }
  }

  Future<void> createStudent(Student student) async {
    studentsLoading.value = true;
    try {
      var response = await studentProvider.create(student);
      print(response.body);
    } finally {
      studentsLoading.value = false;
    }
  }

  Future<void> updateStudent(Student student) async {
    studentsLoading.value = true;
    try {
      var response = await studentProvider.update(student);
      print(response.body);
    } finally {
      studentsLoading.value = false;
    }
  }

  Future<void> removeStudent(String id) async {
    studentsLoading.value = true;
    try {
      var response = await studentProvider.remove(id);
      print(response.body);
    } finally {
      studentsLoading.value = false;
    }
  }
}

class StudentProvider extends GetConnect {
  @override
  void onInit() {
    httpClient.baseUrl = 'http://localhost:3000';
  }

  Future<Response<List<Student>>> getAll() =>
      get('/students', decoder: Student.listFromJson);
  Future<Response<Student>> getById(String id) =>
      get('/students/$id', decoder: Student.fromJson);
  Future<Response<Student>> create(Student student) =>
      post('/students', student.toJson(), decoder: Student.fromJson);
  Future<Response<Student>> update(Student student) =>
      put('/students/${student.id}', student.toJson(),
          decoder: Student.fromJson);
  Future<Response> remove(String id) => delete('/students/$id');
}

class Student {
  final String id;
  final String? name;
  final String? email;

  Student({required this.id, this.name, this.email});

  // fromJson
  factory Student.fromJson(dynamic json) {
    return Student(
      id: json['id'],
      name: json['name'],
      email: json['email'],
    );
  }

  // listFromJson
  static List<Student> listFromJson(dynamic json) {
    return List<Student>.from(json.map((student) => Student.fromJson(student)));
  }

  // toJson
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
    };
  }

  // toString
  @override
  String toString() {
    return 'Student{id: $id, name: $name, email: $email}';
  }
}
```

### 2.2. Touch the button and see the log

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kk3v7az02mscm4jgcwnt.png)