code.gs:
function doGet(request){
// Open Google Sheet using ID
var sheet = SpreadsheetApp.openById("1OOArrqjOqmD4GiJOWlluZ4woTMH_qaV6RKv4JXnT3Hk");
// Get all values in active sheet
var values = sheet.getActiveSheet().getDataRange().getValues();
var data = [];
for (var i = values.length - 1; i >= 0; i--) {
// Get each row
var row = values[i];
// Create object
var feedback = {};
feedback['name'] = row[0];
feedback['email'] = row[1];
feedback['mobile_no'] = row[2];
feedback['feedback'] = row[3];
// Push each row object in data
data.push(feedback);
}
// Return result
return ContentService
.createTextOutput(JSON.stringify(data))
.setMimeType(ContentService.MimeType.JSON);
}
function doPost(request){
// Open Google Sheet using ID
var sheet = SpreadsheetApp.openById("1OOArrqjOqmD4GiJOWlluZ4woTMH_qaV6RKv4JXnT3Hk");
var result = {"status": "SUCCESS"};
try{
// Get all Parameters
var name = request.parameter.name;
var email = request.parameter.email;
var mobileNo = request.parameter.mobileNo;
var feedback = request.parameter.feedback;
// Append data on Google Sheet
var rowData = sheet.appendRow([name, email, mobileNo, feedback]);
}catch(exc){
// If error occurs, throw exception
result = {"status": "FAILED", "message": exc};
}
// Return result
return ContentService
.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON);
}
Dart code
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
import '../model/form.dart';
/// FormController is a class which does work of saving FeedbackForm in Google Sheets using
/// HTTP GET request on Google App Script Web URL and parses response and sends result callback.
class FormController {
// Google App Script Web URL.
static const String URL =
"https://script.google.com/macros/s/AKfycbyAaNh-1JK5pSrUnJ34Scp3889mTMuFI86DkDp42EkWiSOOycE/exec";
// Success Status Message
static const STATUS_SUCCESS = "SUCCESS";
/// Async function which saves feedback, parses [feedbackForm] parameters
/// and sends HTTP GET request on [URL]. On successful response, [callback] is called.
void submitForm(
FeedbackForm feedbackForm, void Function(String) callback) async {
try {
await http.post(URL, body: feedbackForm.toJson()).then((response) async {
if (response.statusCode == 302) {
var url = response.headers['location'];
await http.get(url).then((response) {
callback(convert.jsonDecode(response.body)['status']);
});
} else {
callback(convert.jsonDecode(response.body)['status']);
}
});
} catch (e) {
print(e);
}
}
/// Async function which loads feedback from endpoint URL and returns List.
Future> getFeedbackList() async {
return await http.get(URL).then((response) {
var jsonFeedback = convert.jsonDecode(response.body) as List;
return jsonFeedback.map((json) => FeedbackForm.fromJson(json)).toList();
});
}
}
import 'package:flutter/material.dart';
import 'package:google_sheets_app/feedback_list.dart';
import 'controller/form_controller.dart';
import 'model/form.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Google Sheet Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Google Sheet Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
// Create a global key that uniquely identifies the Form widget
// and allows validation of the form.
//
// Note: This is a `GlobalKey`,
// not a GlobalKey.
final _formKey = GlobalKey();
final _scaffoldKey = GlobalKey();
// TextField Controllers
TextEditingController nameController = TextEditingController();
TextEditingController emailController = TextEditingController();
TextEditingController mobileNoController = TextEditingController();
TextEditingController feedbackController = TextEditingController();
// Method to Submit Feedback and save it in Google Sheets
void _submitForm() {
// Validate returns true if the form is valid, or false
// otherwise.
if (_formKey.currentState.validate()) {
// If the form is valid, proceed.
FeedbackForm feedbackForm = FeedbackForm(
nameController.text,
emailController.text,
mobileNoController.text,
feedbackController.text);
FormController formController = FormController();
_showSnackbar("Submitting Feedback");
// Submit 'feedbackForm' and save it in Google Sheets.
formController.submitForm(feedbackForm, (String response) {
print("Response: $response");
if (response == FormController.STATUS_SUCCESS) {
// Feedback is saved succesfully in Google Sheets.
_showSnackbar("Feedback Submitted");
} else {
// Error Occurred while saving data in Google Sheets.
_showSnackbar("Error Occurred!");
}
});
}
}
// Method to show snackbar with 'message'.
_showSnackbar(String message) {
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Form(
key: _formKey,
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: nameController,
validator: (value) {
if (value.isEmpty) {
return 'Enter Valid Name';
}
return null;
},
decoration: InputDecoration(labelText: 'Name'),
),
TextFormField(
controller: emailController,
validator: (value) {
if (!value.contains("@")) {
return 'Enter Valid Email';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(labelText: 'Email'),
),
TextFormField(
controller: mobileNoController,
validator: (value) {
if (value.trim().length != 10) {
return 'Enter 10 Digit Mobile Number';
}
return null;
},
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Mobile Number',
),
),
TextFormField(
controller: feedbackController,
validator: (value) {
if (value.isEmpty) {
return 'Enter Valid Feedback';
}
return null;
},
keyboardType: TextInputType.multiline,
decoration: InputDecoration(labelText: 'Feedback'),
),
],
),
)),
RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: _submitForm,
child: Text('Submit Feedback'),
),
RaisedButton(
color: Colors.lightBlueAccent,
textColor: Colors.black,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FeedbackListScreen(),
));
},
child: Text('View Feedback'),
),
],
),
),
);
}
}
/// FeedbackForm is a data class which stores data fields of Feedback.
class FeedbackForm {
String name;
String email;
String mobileNo;
String feedback;
FeedbackForm(this.name, this.email, this.mobileNo, this.feedback);
factory FeedbackForm.fromJson(dynamic json) {
return FeedbackForm(
"${json['name']}",
"${json['email']}",
"${json['mobileNo']}",
"${json['feedback']}"
);
}
// Method to make GET parameters.
Map toJson() => {
'name': name,
'email': email,
'mobileNo': mobileNo,
'feedback': feedback
};
}