DEV Community

Cover image for Build Full stack application using Flutter ft. Dart frog and MongoDB. Part 1
Md. Mobin
Md. Mobin

Posted on • Edited on

13 1

Build Full stack application using Flutter ft. Dart frog and MongoDB. Part 1

I am back again on the track of a series of learning.

Do you know we can build a Full-stack application using Flutter only?

Yes, We can build Full stack applications with the help of the dart-frog library.

We are going to build in this series a simple Pizza-shop application.

In this part, We are going to learn about how Dart-frog basically works with static data.

What is Dart-Frog?

Dart-frog is not directly or officially related to the flutter but it is a framework designed in the dart to create a minimalist back end.

meme1

In addition, Dart Frog is intended to help Flutter/Dart developers maximize their productivity by having a unified tech stack that enables sharing tooling, models, and more!

Thanks to verygood.ventures

dart-frog

Installing Dart-frog



//📦 Install the dart_frog cli from pub.dev
dart pub global activate dart_frog_cli


Enter fullscreen mode Exit fullscreen mode

Creating a project



dart_frog create pizza_shop


Enter fullscreen mode Exit fullscreen mode

Start the server



dart_frog dev 


Enter fullscreen mode Exit fullscreen mode

Note: By default 8080 port is used to change via --port.

Lets Explore

How do routes work?

"routes" folder contains routes for example "index.dart" is "/" home route and if we have to create another route then create a new folder in "routes" in with route_name and create a dart file named the same as the endpoint with onRequestFunction().

import 'package:dart_frog/dart_frog.dart';
Response onRequest(RequestContext context) {
return Response(body: 'Hello world');
}
view raw index.dart hosted with ❤ by GitHub

All route handlers have access to a RequestContext which can be used to access the incoming request as well as dependencies provided to the request context.

HTTP Method

We can identify types of HTTP requests via context.request.method

import 'package:dart_frog/dart_frog.dart';
Response onRequest(RequestContext context) {
// Access the incoming request.
final request = context.request;
// Access the HTTP method.
final method = request.method.value;
return Response(body: 'This is a $method request.');
}

for the same, we can get also

  • Query parameters: context.request.uri.queryParameters
  • Headers: context.request.headers
  • Body: await context.request.body()
  • Json Data: await context.request.json()
  • Form Data: await context.request.formData()

Let's start working on the Pizza shop

..........................................

Create models for pizzas and orders.

  • Add json_annotation: ^4.7.0 in pubspec.yaml for serialization.
  • Step create a new folder named models and a file named pizza_models.dart using JSON annotation.
import 'package:json_annotation/json_annotation.dart';
@JsonSerializable()
class PizzaModel {
PizzaModel({this.name, this.price, this.image, this.description, this.id});
factory PizzaModel.fromJson(Map<String, dynamic> json) =>
_$PizzaModelFromJson(json);
final String? name;
final int? price;
final String? id;
final String? image;
final String? description;
Map<String, dynamic> toJson() => _$PizzaModelToJson(this);
}
PizzaModel _$PizzaModelFromJson(Map<String, dynamic> json) {
return PizzaModel(
name: json['name'] as String?,
price: json['price'] as int?,
image: json['image'] as String?,
description: json['description'] as String?,
id: json['id'] as String?,
);
}
Map<String, dynamic> _$PizzaModelToJson(PizzaModel instance) =>
<String, dynamic>{
'name': instance.name,
'price': instance.price,
'image': instance.image,
'description': instance.description,
'id': instance.id
};
  • create order_models.dart in the same folder.
    // ignore_for_file: lines_longer_than_80_chars
    import 'package:json_annotation/json_annotation.dart';
    @JsonSerializable()
    class OrderModel {
    OrderModel(
    this.userId,
    this.pizzaId,
    this.address,
    this.phoneNumber,
    this.status,
    this.id,
    );
    factory OrderModel.fromJson(Map<String, dynamic> json) =>
    $OrderModelFromJson(json);
    Map<String, dynamic> toJson() => $OrderModelToJson(this);
    final String? userId;
    final String? pizzaId;
    final String? address;
    final String? phoneNumber;
    final String? status;
    final int id;
    }
    OrderModel $OrderModelFromJson(Map<String, dynamic> json) {
    return OrderModel(
    json['user_id'] as String?,
    json['pizza_id'] as String?,
    json['address'] as String?,
    json['phone_number'] as String?,
    json['status'] as String?,
    json['id'] as int,
    );
    }
    Map<String, dynamic> $OrderModelToJson(OrderModel instance) =>
    <String, dynamic>{
    'user_id': instance.userId,
    'pizza_id': instance.pizzaId,
    'address': instance.address,
    'phone_number': instance.phoneNumber,
    'status': instance.status,
    'id': instance.id,
    };

meme

Creating Endpoints for fetching the list of pizzas or specific using pizza_id.

  • Before creating the endpoint, We need a List of orders and pizzas, so create a new folder in the project name utlis and inside this create a dart file(constant.dart) with the following content.
import '../models/order_models.dart';
import '../models/pizza_models.dart';
List<PizzaModel> pizzas = [
PizzaModel.fromJson(
{
'id': 50,
'name': 'Baby Bell Peppers',
'description': 'BASIL LEAVES, WATER, SEA SALT, SUNFLOWER OIL',,
'image': 'https://assets.zumepizza.com/public/7650vx0h.png',
'price': 10
},
),
PizzaModel.fromJson(
{
'id': 6,
'name': 'Basil',
'description': 'BASIL LEAVES, WATER, SEA SALT, SUNFLOWER OIL',,
'image': 'https://assets.zumepizza.com/public/9pb5d2k4.png',
'price': 11
},
),
PizzaModel.fromJson(
{
'id': 110,
'name': 'Daiya Vegan Mozzarella',
'description':
'FILTERED WATER, TAPIOCA FLOUR, EXPELLER PRESSED NON-GMO CANOLA AND/OR SAFFLOWER OIL, COCONUT OIL, PEA PROTEIN, SALT, VEGAN NATURAL FLAVOURS, INACTIVE YEAST, VEGETABLE GLYCERIN, XANTHAN GUM, CITRIC ACID, TITANIUM DIOXIDE',
'price': 12,
'image': 'https://assets.zumepizza.com/public/oo9dpuia.png'
},
),
PizzaModel.fromJson(
{
'id': 74,
'name': 'Kalamata Olives',
'description': 'KALAMATA OLIVES, WATER, SEA SALT, SUNFLOWER OIL',
'image': 'https://assets.zumepizza.com/public/ezuum3ch.png',
'price': 5
},
)
];
List<OrderModel> orders = [
OrderModel.fromJson({
'id': 1,
'user_id': '1',
'pizza_id': '6',
'address': '1234 Main St',
'phone_number': '1234567890',
'status': 'pending'
}),
OrderModel.fromJson({
'id': 2,
'user_id': '1',
'pizza_id': '50',
'address': '1234 Main St',
'phone_number': '1234567890',
'status': 'pending'
}),
OrderModel.fromJson({
'id': 3,
'user_id': '123',
'pizza_id': '74',
'address': '1234 Main St',
'phone_number': '1234567890',
'status': 'pending'
}),
];
view raw constant.dart hosted with ❤ by GitHub
  • create a dart file named pizzas.dart. This method will be a GET to return a list of pizzas if no id query parameter is provided otherwise it will return specific pizza details.
import 'package:dart_frog/dart_frog.dart';
import '../models/pizza_models.dart';
import '../utlis/constant.dart';
Response onRequest(RequestContext context) {
//check if the request is a GET request
if (context.request.method == HttpMethod.get) {
//check if query parameter is present
final params = context.request.uri.queryParameters;
if (params.containsKey('id')) {
//return the pizza with the id
final id = params['id'];
// ignore: require_trailing_commas
final pizza = pizzas.firstWhere(
(element) => element.id == id,
orElse: () => PizzaModel.fromJson({}),
);
if (pizza.id != null) {
return Response.json(body: {'data': pizza});
}
return Response.json(
statusCode: 404,
body: {'message': 'Pizza not found'},
);
}
return Response.json(body: {'data': pizzas});
}
return Response.json(
statusCode: 404,
body: {'message': 'Method not allowed'},
);
}
view raw pizzas.dart hosted with ❤ by GitHub

OUTPUT

/pizzas

Fetching order

  • For fetching orders, we are going to create a GET method with the query parameter user_id for getting the list of orders.
import 'package:dart_frog/dart_frog.dart';
import '../utlis/constant.dart';
Response onRequest(RequestContext context) {
//check if the request is a GET request
if (context.request.method == HttpMethod.get) {
//check if user_id is present
final params = context.request.uri.queryParameters;
if (params.containsKey('user_id')) {
final userId = params['user_id'];
final userOrders = orders.where((element) => element.userId == userId);
if (orders.isNotEmpty) {
return Response.json(body: {'data': userOrders.toList()});
}
}
return Response.json(body: {'message': 'User id not found'});
}
return Response.json(
statusCode: 404,
body: {'message': 'Method not allowed'},
);
}

output 2

Creating order

  • For creating an order we required the following fields user_id,pizza_id, address, and phone number.
  • Method should post only.
  • Will check if the headers content type is application/JSON or not.

  • Will also check if the pizza_id is valid or not.

  • after creating the order, we will return order-id to the user.

// ignore_for_file: avoid_dynamic_calls, noop_primitive_operations
import 'package:dart_frog/dart_frog.dart';
import '../models/order_models.dart';
import '../utlis/constant.dart';
Future<Response> onRequest(RequestContext context) async {
//check if the request is a POST request
if (context.request.method == HttpMethod.post) {
//check if headers is application/json
final contentType = context.request.headers['Content-Type'];
if (contentType == 'application/json') {
//check if body is present
final body = await context.request.json();
if (body != null &&
body['pizza_id'] != null &&
body['user_id'] != null &&
body['address'] != null &&
body['phone_number'] != null) {
//check valid pizza id
final isValidPizzaId =
pizzas.any((element) => element.id == body['pizza_id']);
if (isValidPizzaId) {
orders.add(
OrderModel.fromJson({
'id': DateTime.now().millisecondsSinceEpoch.toInt(),
'pizza_id': body['pizza_id'],
'user_id': body['user_id'],
'address': body['address'],
'phone_number': body['phone_number'],
}),
);
return Response.json(
statusCode: 201,
body: {
'message':
'Order created successfully with order id: ${orders.last.id}'
},
);
} else {
return Response.json(
statusCode: 404,
body: {'message': 'Invalid pizza id'},
);
}
} else {
return Response.json(
statusCode: 404,
body: {'message': 'All fields are required'},
);
}
}
return Response.json(
statusCode: 404,
body: {'message': 'Content-Type must be application/json'},
);
}
return Response.json(
statusCode: 404,
body: {'message': 'Method not allowed'},
);
}

output 3

We are done .....................

In the next part, we are going to connect MongoDB for persisting data.

part-2

Stay Tuned .....

Follow me:

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (4)

Collapse
 
panicoli0 profile image
Pablo Ariel Nicoli • Edited

How to connect dart-frog with mongodb cloud?

Collapse
 
djsmk123 profile image
Md. Mobin

Hi pablo sorry for late reply, you can dart-frog to Atlas using following code
var db = await Db.create("mongodb+srv://:@:/?");
await db.open();

and for more info
pub.dev/packages/mongo_dart

I hope it will help you.

Collapse
 
george_lee_e2ca2ed8be27c7 profile image
George Lee • Edited

I am having issues using JSON annotation. Would you please show how to do this?

Collapse
 
djsmk123 profile image
Md. Mobin

Hi George, you can refer to this article.
medium.com/flutter-community/gener...

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay