Not getting values in Web view fast enough - database

Hey the problem I am having is kinda unusal..
So am using webviews and as the intialUrl I am using a value I get from the Google cloud_ firestore.. Now to retrieve this link from my fireStore database it takes about 2seconds and during that time my code is running and is thinking that the 'thankGod' variable is empty.. So even the Text widget says that the 'thankGod' variable is null for the first 2seconds and then returns the value after.. But this is not good cause my webView is using the 'thankGod' variable when it is empty.. Here is my code.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:webview_flutter/webview_flutter.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
final Completer<WebViewController> _completer = Completer<WebViewController>();
DocumentReference documentReference = Firestore.instance.collection('dailyPictures').document('t1');
Future<void> getData() async{
await documentReference.get().then((datasnapshots) {
setState(() {
thankGod = datasnapshots.data['picture1'];
});
});
}
String thankGod;
#override
void initState() {
super.initState();
getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(1800),
),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.fromLTRB(
20,
20,
20,
20
),
child:
Text(
thankGod,
style: TextStyle(
color: Colors.white,
fontSize:32
),
)
WebView(
initialUrl: thankGod,
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: ((WebViewController webViewController){
_completer.complete(webViewController);
}),
),
));
}
}
Please I need help.. Help me share this question

make your return type String for your getData function;
Future<String> getData() async {
DocumentSnapshot = await documentReference.get();
return datasnapshots.data['picture1'];
}
and use FutureBuilder to get your data and build your WebView;
FutureBuilder<String>(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
String initialUrl = snapshot.data;
return WebView(
initialUrl: initialUrl,
debuggingEnabled: true,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: ((WebViewController webViewController) {
_completer.complete(webViewController);
}),
);
}
return CircularProgressIndicator();
},
)
note: You don't need call getData() inside initState.

Related

How to create a form using dynamic fields from a JSON array in Flutter

I want to create a form with dynamic fields. The fields are fetched from a database; these are determined by a user on the web application and then displayed to another user on the mobile application so the fields keep changing.
Although there are no errors in the code, the form does not display. I have simplified it to a single input field so as to test the logic. Below is what I have tried so far:
the file to create the form :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:mne/Network/api.dart';
import 'form_model.dart';
class CreateForm extends StatefulWidget {
const CreateForm({Key? key}) : super(key: key);
#override
State<CreateForm> createState() => _CreateFormState();
}
class _CreateFormState extends State<CreateForm> {
late List<Map<String, dynamic>> _values;
final List<FormFields> _formFields = <FormFields>[];
#override
void initState() {
super.initState();
_values = [];
}
Future<List<FormFields>> _fetchFormFields() async {
var res = await Network().getData('company/fields');
var fields = <FormFields>[];
if (res.StatusCode == 200) {
var body = json.decode(res.body);
var tdata = body['data'];
var formsJson = tdata;
for (var formJson in formsJson) {
fields.add(FormFields.fromJson(formJson));
}
}
return fields;
}
_displayForm(index) {
_fetchFormFields().then((value) {
_formFields.addAll(value);
});
if (_formFields[index].type == "text") {
return Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
decoration: InputDecoration(
labelText: _formFields[index].name,
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(10)),
),
onChanged: (val) {},
));
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(10),
child: Column(
children: [
Flexible(
child: ListView.builder(
shrinkWrap: true,
itemCount: _formFields.length,
itemBuilder: (context, index) {
return _displayForm(index);
}))
],
)));
}
}
the form model:
class FormFields {
String name;
String type;
String option;
FormFields({required this.name, required this.type, required this.option});
factory FormFields.fromJson(Map<String, dynamic> json) => FormFields(
name: json['name'],
type: json['type'],
option: json['option'],
);
Map<String, String> toJson() =>
{'name': name, 'type': type, 'option': option};
}
I want a circular progress indicator to show loading. I also want the user to move from the login directly to a display of the form so I put the create form class inside another one, to make it easier to reference in the login button. I called it test :
import 'package:flutter/material.dart';
import 'package:mne/Forms/create_form.dart';
class Test extends StatefulWidget {
const Test({Key? key}) : super(key: key);
#override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
bool _isLoading = true;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
if (_isLoading)
Container(
alignment: Alignment.center,
child: ElevatedButton(
child: const Text('Add Form'),
onPressed: () async {
setState(() {
_isLoading = false;
});
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CreateForm()));;
if (!mounted) return;
setState(() {
_isLoading = true;
});
},
))
else
const Center(
child: CircularProgressIndicator(backgroundColor: Color.fromRGBO(0, 161, 39, 1)),
)
]));
}
}
Currently, after clicking on the login button which navigates to the test page it displays the add form button.
On clicking the add form button, the circular progress indicator displays very briefly before displaying a blank page. Should I perhaps add all the possible field type options for it to work? Please let me know where I have gone wrong thanks

Same date is displaying for all the notes in flutter. Date is not updating dynamically

I am a beginner in flutter and I am building a simple note-taking app. Whenever a user creates a note, the date month, and year of creation will get inserted into SQflite DB and I am fetching the same on the main screen. But for all other notes also same date month and year are displaying. I don't know where it went wrong, any help here, please. I am stuck in this for the past 2 days. I have checked other answers in StackOverflow, from there I learnt the implementation of date, but couldn't resolve this problem.
Database Helper Class
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'model_notes.dart';
class DatabaseHelper {
static final _databaseName = "myNote.db";
static final _databaseVersion = 1;
static final table = 'notes_table';
static final columnId = 'id';
static final columnTitle = 'title';
static final columnBody = 'body';
static final columnDate = 'date';
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await initDatabase();
return _database;
}
initDatabase() async {
String path = join(await getDatabasesPath(), _databaseName);
return await openDatabase(path,
version: _databaseVersion, onCreate: _onCreate);
}
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY AUTOINCREMENT,
$columnTitle TEXT NOT NULL,
$columnBody TEXT NOT NULL,
$columnDate TEXT NOT NULL
)
''');
}
Future<int> insert(Note note) async {
Database db = await instance.database;
if (note.title.trim().isEmpty) note.title = 'Untitled Note';
return await db.insert(table, {'title': note.title, 'body': note.body, 'date': note.date});
}
Future<List<Note>> getNotesFromDB() async {
final db = await database;
List<Note> notesList = [];
List<Map> maps = await db.query(table);
if (maps.length > 0) {
maps.forEach((map) {
notesList.add(Note.fromMap(map));
});
}
return notesList;
}
}
This is my note model class
import 'db_operations.dart';
class Note {
int id;
String title;
String body;
String date;
Note(this.id, this.title, this.body, this.date);
Note.fromMap(Map<String, dynamic> map) {
id = map['id'];
title = map['title'];
body = map['body'];
date = map['date'];
}
Map<String, dynamic> toMap() {
return {
DatabaseHelper.columnId: id,
DatabaseHelper.columnTitle: title,
DatabaseHelper.columnBody: body,
DatabaseHelper.columnDate: date,
};
}
#override
String toString() {
return '$title, $date';
}
}
This is where I am adding Notes
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:note_taking_app/constants/buttons_and_icons_misc(classes).dart';
import 'package:note_taking_app/db/db_operations.dart';
import 'package:note_taking_app/db/model_notes.dart';
final bodyController = TextEditingController();
final headerController = TextEditingController();
final dbHelper = DatabaseHelper.instance;
String formattedDate = DateFormat.yMMMd('en_US').format(DateTime.now());
class AddingNotes extends StatefulWidget {
#override
_AddingNotesState createState() => _AddingNotesState();
}
class _AddingNotesState extends State<AddingNotes> {
#override
void initState() {
super.initState();
bodyController.clear();
headerController.clear();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backwardsCompatibility: true,
leading: LeadingIcon(
callBack: () {
Navigator.pop(context);
},
),
backgroundColor: Colors.white.withOpacity(0.4),
actions: <Widget>[
ActionsIconButton(
icon: Icon(undo, color: black),
callBack: () {
debugPrint('undo tapped');
},
),
ActionsIconButton(
icon: Icon(redo, color: black),
callBack: () {
debugPrint('redo tapped');
},
),
ActionsIconButton(
icon: Icon(save, color: black),
callBack: () async {
String title = headerController.text;
String body = bodyController.text;
Note note = Note(20, title, body, formattedDate);
var value = await dbHelper.insert(note);
Navigator.pop(context);
},
)
],
),
body: Container(
color: Colors.white.withOpacity(0.4),
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Column(
children: [
HeaderBody(
textEditingController: headerController,
),
SizedBox(
height: 32.0,
),
Expanded(
child: NotesBody(
textEditingController: bodyController,
),
),
],
),
),
),
);
}
}
This is where I am displaying notes
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:note_taking_app/constants/buttons_and_icons_misc(classes).dart';
import 'package:note_taking_app/constants/text_and_decorations(methods).dart';
import 'package:note_taking_app/db/model_notes.dart';
import 'package:note_taking_app/ui/adding_notes.dart';
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
List<Note> noteList = [];
#override
void initState() {
super.initState();
dbHelper.initDatabase();
setNotesFromDB();
}
setNotesFromDB() async {
print("Entered setNotes in main page");
var fetchedNotes = await dbHelper.getNotesFromDB();
setState(() {
noteList = fetchedNotes;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: mainScreenAppBar,
floatingActionButton: FAB(
whatToDo: () {
gotoAddingNotesPage(context);
},
),
body: SafeArea(
child: ListView.builder(
itemCount: noteList.length,
itemBuilder: (context, index) {
return TileCard(
titleText: ('${noteList[index].title}'),
dateText: ('${noteList[index].date}'),
);
},
),
),
);
}
gotoAddingNotesPage(BuildContext context) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddingNotes()),
).then((value) => setState(() {
setNotesFromDB();
}));
}
}
This is my TileCard class where I've declared dateText widget
class TileCard extends StatelessWidget {
final String titleText;
final String dateText;
const TileCard({#required this.titleText, #required this.dateText});
#override
Widget build(BuildContext context) {
return Container(
height: 90,
child: Card(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
elevation: 0,
margin: const EdgeInsets.all(8.0),
child: ListTile(
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
title: Text(
titleText,
style: TextStyle(fontWeight: FontWeight.w700),
),
tileColor: Colors.grey.withOpacity(0.2),
subtitle: Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text(dateText),
),
),
),
);
}
}
I have added image, this is how it looks now.

I am creating note app in flutter and stuck in sqflite, how can I pass my title and body to insert method

I am building a simple note app, but I am stuck at saving the data (title and body) using SQLite.
DataBaseHelper class
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'model_notes.dart';
class DatabaseHelper {
static final _databaseName = "myNote.db";
static final _databaseVersion = 1;
static final table = 'notes_table';
static final columnId = 'id';
static final columnTitle = 'title';
static final columnBody = 'body';
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
}
_initDatabase() async {
String path = join(await getDatabasesPath(), _databaseName);
return await openDatabase(path,
version: _databaseVersion,
onCreate: _onCreate);
}
Future _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY AUTOINCREMENT,
$columnTitle TEXT NOT NULL,
$columnBody TEXT NOT NULL
)
''');
}
Future<int> insert(Note note) async {
Database db = await instance.database;
return await db.insert(table, {'title': note.title, 'body': note.body});
}
This is the Model Class for Notes
import 'db_operations.dart';
class Note {
int id;
String title;
String body;
Note(this.id, this.title, this.body);
Note.fromMap(Map<String, dynamic> map) {
id = map['id'];
title = map['title'];
body = map['body'];
}
Map<String, dynamic> toMap(){
return {
DatabaseHelper.columnId : id,
DatabaseHelper.columnTitle : title,
DatabaseHelper.columnBody : body
};
}
}
and this is where I'm calling insert method (class name = adding_notes.dart)
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:note_taking_app/constants/buttons_and_icons_misc(classes).dart';
import 'package:note_taking_app/db/db_operations.dart';
import 'package:note_taking_app/db/model_notes.dart';
import 'package:sqflite/sqflite.dart';
import 'main_screen.dart';
final bodyController = TextEditingController();
final headerController = TextEditingController();
final dbHelper = DatabaseHelper.instance;
class AddingNotes extends StatefulWidget {
#override
_AddingNotesState createState() => _AddingNotesState();
}
class _AddingNotesState extends State<AddingNotes> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backwardsCompatibility: true,
leading: LeadingIcon(
callBack: () {
Navigator.pop(context);
},
),
backgroundColor: Colors.white.withOpacity(0.4),
actions: <Widget>[
ActionsIconButton(
icon: Icon(undo, color: black),
callBack: () {
debugPrint('undo tapped');
},
),
ActionsIconButton(
icon: Icon(redo, color: black),
callBack: () {
debugPrint('redo tapped');
},
),
ActionsIconButton(
icon: Icon(save, color: black),
callBack: () async {
debugPrint(bodyController.text);
debugPrint(headerController.text);
getHeaderDataToMainScreen(context);
String title = headerController.text;
String body = bodyController.text;
/*This is where I am calling insert method*/
dbHelper.insert(title, body);
},
)
],
),
body: Container(
color: Colors.white.withOpacity(0.4),
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Column(
children: [
HeaderBody(
textEditingController: headerController,
),
SizedBox(
height: 32.0,
),
Expanded(
child: NotesBody(
textEditingController: bodyController,
),
),
],
),
),
),
);
}
}
getHeaderDataToMainScreen(BuildContext context){
Navigator.push(context,
MaterialPageRoute(
builder: (context) => MainScreen(
heading : headerController.text,
)
)
);
}
It is showing too many positional arguments expected 1 found 2. I know I need to send 1 argument, but how can I send both title and body as 1 argument. Maybe through List I can send it but I don't know how to do that. Any help here guys, I'm stuck at this for the past 5 days.
Check the example below that i have created based on the code you provided.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'db_operations.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: AddingNotes(),
));
}
final bodyController = TextEditingController();
final headerController = TextEditingController();
final dbHelper = DatabaseHelper.instance;
class AddingNotes extends StatefulWidget {
#override
_AddingNotesState createState() => _AddingNotesState();
}
class _AddingNotesState extends State<AddingNotes> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.add,
color: Colors.black,
),
),
),
backgroundColor: Colors.white.withOpacity(0.4),
actions: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
debugPrint('undo tapped');
},
child: Icon(
Icons.undo,
color: Colors.black,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () {
debugPrint('redo tapped');
},
child: Icon(
Icons.redo,
color: Colors.black,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () async {
debugPrint(bodyController.text);
debugPrint(headerController.text);
//getHeaderDataToMainScreen(context);
String title = headerController.text;
String body = bodyController.text;
Note note = Note(20, title, body);
var value = await dbHelper.insert(note);
print("if 1 is return then insert success and 0 then not inserted : $value");
},
child: Icon(
Icons.save,
color: Colors.black,
),
),
)
],
),
body: Container(
color: Colors.white.withOpacity(0.4),
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Column(
children: [
TextField(
controller: headerController,
),
SizedBox(
height: 32.0,
),
Expanded(
child: TextField(
controller: bodyController,
),
),
],
),
),
),
);
}
}
// getHeaderDataToMainScreen(BuildContext context) {
// Navigator.push(context,
// MaterialPageRoute(
// builder: (context) =>
// MainScreen(
// heading: headerController.text,
// )
// )
// );
// }
class Note {
int id;
String title;
String body;
Note(this.id, this.title, this.body);
Note.fromMap(Map<String, dynamic> map) {
id = map['id'];
title = map['title'];
body = map['body'];
}
Map<String, dynamic> toMap() {
return {
DatabaseHelper.columnId: id,
DatabaseHelper.columnTitle: title,
DatabaseHelper.columnBody: body
};
}
}
This is just a sample demo example added every thing in one file and made many changes. change it as per your needs.
You don't need a auto increment id as you have given it in the database. Run the app and let me know if it works.

Add data instead of overwriting it

When I use pop up AddPlanScreen to add a note to the widget, it overwrites the document instead of adding it. Registering, logging and setting data work properly.
What I've tried to do:
Using FirebaseFirestore.instance.runTransaction but I couldn't use + operator for String as I add data to map.
set(..., SetOptions(merge:true))
update method
Do I have to try to create a new Map and add data there? I am new to programming and will be very grateful for any suggestions.
This is a method I use to set and fetch data
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class MyProvider extends ChangeNotifier {
Map<String, dynamic> _names = {};
String name(String key) => _names[key];
void setName(String key, String newString) {
_names[key] = newString;
var firebaseUser = FirebaseAuth.instance.currentUser;
FirebaseFirestore.instance
.collection('Notes')
.doc(firebaseUser.uid)
.set(_names);
}
void fetchData() {
var firebaseUser = FirebaseAuth.instance.currentUser;
FirebaseFirestore.instance
.collection('Notes')
.doc(firebaseUser.uid)
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
var data = documentSnapshot.data();
_names = data;
} else {
print('The document does not exist on the database');
}
});
}
}
This is Planner Screen where I show all the notes
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:my_planner_app/widgets/my_provider.dart';
import 'file:///C:/Users/krisk/AndroidStudioProjects/planner_app/lib/widgets/weekday_card.dart';
import 'package:provider/provider.dart';
class PlannerScreen extends StatefulWidget {
static const String id = 'planner_screen';
#override
_PlannerScreenState createState() => _PlannerScreenState();
}
class _PlannerScreenState extends State<PlannerScreen> {
Widget build(BuildContext context) {
Provider.of<MyProvider>(context, listen: false)
.fetchData();
var size = MediaQuery.of(context).size;
final double itemHeight = (size.height - 24) / 2;
final double itemWidth = size.width / 2;
return Scaffold(
backgroundColor: Color(0xFFcf9e9f),
body: Container(
child: GridView(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
childAspectRatio: (itemWidth / itemHeight),
),
children: <Widget>[
WeekDayCard(
text: '',
),
WeekDayCard(text: 'Monday' ),
WeekDayCard(text: 'Tuesday'),
WeekDayCard(text: 'Wednesday'),
WeekDayCard(text: 'Thursday'),
WeekDayCard(text: 'Friday'),
WeekDayCard(text: 'Saturday'),
WeekDayCard(text: 'Sunday'),
WeekDayCard(text: 'Notes'),
],
),
),
);
}
}
This is associated WeekDayCard widget
import 'package:flutter/material.dart';
import 'package:my_planner_app/screens/addPlan_screen.dart';
import 'package:provider/provider.dart';
import 'package:my_planner_app/widgets/my_provider.dart';
class WeekDayCard extends StatefulWidget {
WeekDayCard({#required this.text, this.name});
final String name;
final String text;
#override
_WeekDayCardState createState() => _WeekDayCardState();
}
class _WeekDayCardState extends State<WeekDayCard> {
#override
Widget build(BuildContext context) {
return Consumer<MyProvider>(builder: (context, myProvider, child) {
return Card(
color: Color(0xFFFEEFCD),
elevation: 10,
child: Column(
children: [
Text(widget.text),
Text(Provider.of<MyProvider>(context).name(widget.text) ?? ''
),
Expanded(
child: InkWell(
onTap: () {
showModalBottomSheet(
backgroundColor: Color(0xFFFEEFCD),
context: context,
builder: (context) => AddPlanScreen(weekdayName: widget.text),
);
},
),
),
],
),
);
});
}
}
This is associated AddPlanScreen
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_planner_app/widgets/my_provider.dart';
class AddPlanScreen extends StatefulWidget {
final String weekdayName;
const AddPlanScreen({Key key, this.weekdayName}) : super(key: key);
#override
_AddPlanScreenState createState() => _AddPlanScreenState();
}
class _AddPlanScreenState extends State<AddPlanScreen> {
String name;
#override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: TextFormField(
onChanged: (text) {
name = text;
},
decoration: InputDecoration(
border: InputBorder.none,
),
minLines: 10,
maxLines: 30,
autocorrect: false,
),
),
FlatButton(
onPressed: () {
Provider.of<MyProvider>(context, listen: false)
.setName(widget.weekdayName, name);
Navigator.pop(context);
},
color: Colors.blue,
),
],
);
}
}
You should use set only when you are creating a document for the first time and you want to give it a designated ID (not randomly generated by firebase). Or, a second use is when you want to deliberately write over your existing data.
When you want to update a document, or a single value\entry in it, you just use: collection('yourCollection').doc('yourDocID').update({"nameOfnewField": "new data"})
This update method will not overwrite your existing document,it will only add a new field called "nameOfnewField", or if that field already exists, it will write over it only.
i.e if nameOfnewField was a value that was false, when you update it, with .update({"nameOfnewField": "true"}), it becomes true but the rest of the document is not changed.

How to hide a floatingActionButton after insert data flutter?

I use sqflite for flutter database management. In particular, I would like the user to enter the data only once and therefore I would need to hide and disable the button only once the data has been entered. How can I do?
Home Page, where is the button
class Casa extends StatefulWidget {
static const routeName = '/';
#override
_CasaState createState() => _CasaState();
}
class _CasaState extends State<Casa> {
DataRepository _repository;
#override
void initState() {
super.initState();
_repository = SqlRepository();
}
#override
void dispose() async {
await _repository.closeDB();
super.dispose();
}
void getNewItem(BuildContext context) async {
Attivita newItem =
await Navigator.pushNamed<Attivita>(context, AddItemScreen.routeName);
if (newItem != null) {
await _repository.add(newItem);
setState(() {});
}
}
void switchAndUpdate(Attivita item) async {
await _repository.put(item.id, item);
setState(() {});
}
void delete(Attivita item) async {
await _repository.delete(item.id);
setState(() {});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.lightBlue[900],
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.lightBlue[900],),
backgroundColor: Colors.white,
onPressed: () {
getNewItem(context);
},
),
body:
FutureBuilder<List<Attivita>>(
future: _repository.getAll(),
builder:
(BuildContext context, AsyncSnapshot<List<Attivita>> snapshot) {
return ListView.builder(
padding: EdgeInsets.all(8),
itemCount: snapshot.data == null ? 0 : snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Dismissible(
key: UniqueKey(),
background: DecoratedBox(
decoration: BoxDecoration(color: Colors.red),
child: Align(
alignment: Alignment(-0.9, 00),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
direction: DismissDirection.startToEnd,
onDismissed: (direction) {
Attivita item = snapshot.data[index];
snapshot.data.removeAt(index);
delete(item);
},
child: Card(
child: ListTile(
title: Text(snapshot.data[index].nome, style: TextStyle(color: Colors.lightBlue[900]),),
onTap: () {
Navigator.pushNamed(context, DettaglioScreen.routeName, arguments: snapshot.data[index]);
},
onLongPress: () {
switchAndUpdate(snapshot.data[index]);
},
),
),
);
},
);
},
)
),
);
}
}
so i have to add some details, because it is written that "it looks like your post is mostly code; please add some more details"
To check if user put so data you can use:
Use sharedPreferences and store bool value if user entered data.
On initState check if database contains data if yes it means user put some data and you can hide button.
I don't use Sqlite in flutter but I think you can use
List<Map<String, dynamic>> result;
result = await db.query(tableName);
isNotData = result.isEmpty;
Or something similar :) You can do it
Choose one way and store bool value eg. in bool isNotData
When you will have bool value about data you can write:
In _CasaState above initState: bool isNotData;
and in Scaffold in floatingActionButton property:
Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
floatingActionButton: isNotData
? FloatingActionButton(
onPressed: () {},
)
: null,
body: Center(
),
),
),

Resources