reactive_forms Flutter - creating and rendering Groups - forms

Having difficulty figuring how to render groups as their example (https://github.com/joanpablo/reactive_forms#groups-of-groups-grin):
final form = FormGroup({
'personal': FormGroup({
'name': FormControl<String>(validators: [Validators.required]),
'email': FormControl<String>(validators: [Validators.required]),
}),
'phone': FormGroup({
'phoneNumber': FormControl<String>(validators: [Validators.required]),
'countryIso': FormControl<String>(validators: [Validators.required]),
}),
'address': FormGroup({
'street': FormControl<String>(validators: [Validators.required]),
'city': FormControl<String>(validators: [Validators.required]),
'zip': FormControl<String>(validators: [Validators.required]),
}),
});
Im using
ReactiveTextField(formControlName: 'personal', ),
but throws error:
Expected a value of type 'FormControl<dynamic>', but got one of type 'FormGroup'
My aim is to get output like below:
{
"personal": {
"name": "...",
"email": "..."
},
"phone": {
"phoneNumber": "...",
"countryIso": "..."
},
"address": {
"street": "...",
"city": "...",
"zip": "..."
}
}
Any guidance and advice is much appreciated!

Got advice from joanpablo (https://github.com/joanpablo)
Below syntax can be used:
ReactiveTextField(formControlName: 'personal.name', ),
The above code is in case you have for example a ReactiveForm (or a ReactiveFormBuilder) and as a child you have this ReactiveTextField:
ReactiveForm(
formGroup: form,
child: Column(children: [
ReactiveTextField(
formControlName: 'personal.name',
),
]),
),
But you can also have nested ReactiveForm widgets:
ReactiveForm(
formGroup: form,
child: Column(children: [
ReactiveForm(
formGroup: form.control('personal') as FormGroup,
child: Column(children: [
ReactiveTextField(
formControlName: 'name',
),
]),
),
]),
),

Related

Retrieve specific value from Hive Box

In my app, I am using Hive to store data locally. My box is called "favorites" and I managed to store the data in the box with this code:
_save() {
final recipeData = Recipe(
title: widget.recipeDocument['title'],
id: widget.recipeDocument['id'],
price: widget.recipeDocument['price'],
url: widget.recipeDocument['url'],
servings: widget.recipeDocument['servings'],
calories: widget.recipeDocument['calories'],
carbs: widget.recipeDocument['carbs'],
protein: widget.recipeDocument['protein'],
fat: widget.recipeDocument['fat'],
ingredients: widget.recipeDocument['ingredients'],
instructions: widget.recipeDocument['instructions'],);
print('Generated recipeData final $recipeData');
String json =jsonEncode(recipeData);
print('Generated json $json');
final box = Hive.box('favorites'); //<- get an already opened box, no await necessary here
// save recipe information
final Id = widget.recipeDocument['id'];
box.put(Id,json);
On my favorite page, I want to display the title and price in a ListView.
I get data from the box like this:
body: ValueListenableBuilder(
valueListenable: Hive.box('favorites').listenable(),
builder: (context, box, child) {
var box = Hive.box('favorites');
List post = List.from(box.values);
print('List is $post');
The list contains the following:
[
{
"url": "http for URL",
"title": "Bananabread",
"price": "0,77",
"calories": "234",
"carbs": "12",
"fat": "1",
"id": "1",
"protein": "34",
"servings": 1,
"ingredients": [
"2 bananas",
"30 g flour",
"2 eggs"
],
"instructions": [
"1. mix banana and egg.",
"2. add flour.",
"3. bake and enjoy"
]
}
]
Let's say I only want to retrieve the title and price from that. How do I do so?
I tried this:
return ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Text('This shows favorites'),
...post.map(
(p) => ListTile(
title: Text(p[1]),
trailing: Text(p[2]),
),
),
],
);
But this only returns "U" and "R"...so the letters from the word URL, I guess?
Try this. You are accessing the key of the map in the list.
return ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Text('This shows favorites'),
...post.map(
(p) => ListTile(
title: Text(p['url'].toString()),
trailing: Text(p['title'].toString()),
),
),
],
);

How can I get Api data in Streambuilder - Flutter

I have an API, I want to show this API live. When the user removes any data delete live and also add any data from the backend I want to show it live.
Now how can I achieve it in flutter?
I am using Getx(Obx not working) , ListView.builder, and Dio package.
My Page.dart
import 'package:clipboard/clipboard.dart';
import 'package:dio/dio.dart';
import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_phone_direct_caller/flutter_phone_direct_caller.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import 'package:isp_app/src/configs/appColors.dart';
import 'package:isp_app/src/configs/appConfigs.dart';
import 'package:isp_app/src/controllers/baseController.dart';
import 'package:isp_app/src/widgets/customButton.dart';
import 'package:isp_app/src/widgets/customRawText.dart';
import 'package:isp_app/src/widgets/kText.dart';
import 'package:shared_preferences/shared_preferences.dart';
class NewCollectionTab extends StatefulWidget with BaseController {
#override
State<NewCollectionTab> createState() => _NewCollectionTabState();
}
class _NewCollectionTabState extends State<NewCollectionTab>
with BaseController {
final keyRefresh = GlobalKey<RefreshIndicatorState>();
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20),
Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: KText(
text: 'Main',
fontSize: 18,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
SizedBox(height: 10),
Obx( ()=>
ListView.builder(
shrinkWrap: true,
primary: false,
physics: BouncingScrollPhysics(),
itemCount: connectionDataC.connection.length,
itemBuilder: (context, index) {
final item = connectionDataC.connection[index];
return item.connectionStatus == true
? Container()
: InkWell( child: Padding(
padding: EdgeInsets.only(bottom: 10),
child: ListTile(
leading: CircleAvatar(
radius: 30,
backgroundColor: black12,
backgroundImage: NetworkImage(
item.catImg.toString(),
),
),
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
KText(
text: item.userName.toString(),
fontSize: 16,
maxLines: 2,
fontWeight: FontWeight.w600,
),
],
),
SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(
Icons.date_range,
size: 12,
color: black12,
),
SizedBox(width: 5),
KText(
text: DateFormat('dd-MM-yyyy').format(
DateTime.parse(
item.confrmDate.toString(),
),
),
fontSize: 12,
fontWeight: FontWeight.w600,
),
],
),
SizedBox(height: 5),
],
),
subtitle: KText(
text: item.description.toString(),
fontSize: 13,
color: black54,
maxLines: 3,
textAlign: TextAlign.justify,
fontWeight: FontWeight.normal,
),
),
),
);
},
),
),
],
);
}
}
My Controller.dart
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import 'package:isp_app/src/configs/appConfigs.dart';
import 'package:isp_app/src/models/connections.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ConnectionController extends GetxController {
// ignore: unused_field
final _dio = Dio();
// final RxList<dynamic> connectionList = RxList();
final connection = RxList<Connection>();
getconnectionList() async {
print('++++++++++++++++++++++++++++++++++');
try {
final sharedPreferences = await SharedPreferences.getInstance();
final token = sharedPreferences.get('accessToken');
final userName = sharedPreferences.get('loginUserName');
final res = await _dio.get(
'$baseUrl/new_connection/?search=$userName',
options: Options(
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": 'Token $token'
},
),
);
print(res.statusCode);
print(res.headers);
// print(res.body);
// print(res.unauthorized);
print(res.realUri);
print(res.statusMessage);
print(res.data);
print(res.realUri);
print(res.requestOptions);
print('++++++++++++++++++++++++++++++++++');
if (res.statusCode == 200) {
if (res.statusCode! >= 200 && res.statusCode! < 300) {
connection.addAll(
(res.data as List).map((e) => Connection.fromJson(e)).toList());
}
}
} catch (e) {
print(e);
}
}
}
My Api Data demo :
[
{
"id": 1,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "গণপরিবহনে অঘোষিত নিয়ম",
"Phone_Number": "0185455545",
"Description": "পরিবহন খাতের সঙ্গে মো. রুবেল হোসেন যুক্ত সেই ১৯৯৭ সাল থেকে। শুরু থেকেই তিনি ‘পুলিশ পাস’-এর কথা শুনে আসছেন। আদৌ এ নিয়ে কোনো আইন বা নিয়ম আছে কি না, তা জানেন না তিনি। তাঁর মতো অনেক পরিবহনমালিক ও শ্রমিকের একই অবস্থা।\r\n\r\nএত দিন শিক্ষার্থীদের জন্য বাসে অর্ধেক ভাড়ার (হাফ পাস) কথা শোনা গেলেও গণপরিবহনে ভাড়াসংক্রান্ত আরেকটি বিষয় প্রচলিত আছে। সেটিই হলো ওই ‘পুলিশ পাস’। এ ক্ষেত্রে অর্ধেক ভাড়া নয়, কোনো ভাড়াই দিচ্ছেন না অনেক পুলিশ সদস্য।",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 2,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "অবৈধ রসিদে টোল",
"Phone_Number": "0185455545",
"Description": "অবৈধ রসিদ তৈরি করে রাজধানীর যাত্রাবাড়ীর মেয়র হানিফ উড়ালসড়ক থেকে টোল আদায় করার অভিযোগ উঠেছে সংঘবদ্ধ একটি চক্রের বিরুদ্ধে। বিভিন্ন যানবাহনের চালকদের ভয় দেখিয়ে টোলের নামে চাঁদা আদায় করছিল চক্রটি। না দিলে প্রাণনাশের হুমকি দিচ্ছিল তারা।",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 3,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "নরমাল ডেলিভারি হসপিটাল",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 4,
"confrm_date": "2022-01-17T07:14:06",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "কাশেম মঞ্জিল, তানযীমুল উম্মাহ হিফয মাদ্রাসা।",
"Connection_status": false,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 5,
"confrm_date": "2022-01-17T10:42:57",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "হাউজিং মারকাজ মসজিদের পিছনে - nstu teacher 2300 tk router +\r\nline charge 1000+ 360",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 6,
"confrm_date": "2022-01-17T10:43:04",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "মাষ্টার পাড়া - হালিমা ভিলা ৩ তলায়",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 7,
"confrm_date": "2022-01-17T10:44:25",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "মিঠুর কানেকশন আছে এখন , ১ তারিখ নিবে।",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 8,
"confrm_date": "2022-01-17T10:44:49",
"User_name": "User",
"Phone_Number": "0185455545",
"Description": "এতিম খানার পিছনে।",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 10,
"confrm_date": "2022-01-20T07:09:03",
"User_name": "User123",
"Phone_Number": "0185455545",
"Description": "54155",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
},
{
"id": 11,
"confrm_date": "2022-01-20T07:09:48",
"User_name": "12345",
"Phone_Number": "0185455545",
"Description": "546",
"Connection_status": true,
"cat_img": "http://103.137.75.74:82/media/cat_img/LOGO-01.png",
"Connection_by": 1
}
]
Thing is that APIs do not send you "updates" so the client in this case your application does not receive updates when the server, this would require another mechanism like a socket, in which you connect to a server, and listen for active updates, In terms of a normal web api it works as request vs response, the server only responds to a request, so if you want to have a behavior that simulates a "real time" you will need to code a timer, which makes the request every 5 seconds for example, in that case, you will try to fetch new information every certain amount of time. Make sense?

How to add json list items to dropdown search items in Flutter | Dart

I'm creating a dropdown button with search. So I using this package . Here with this package I have problem. The response from the API is like this.
List countries = [
{
'id': '1',
'name': 'Brazil',
},
{
'id': '2',
'name': 'India',
},
{
'id': '3',
'name': 'Japan',
},
{
'id': '4',
'name': 'Tokyo',
},
{
'id': '5',
'name': 'Australia',
},
{
'id': '6',
'name': 'Srilanka',
},
{
'id': '7',
'name': 'Canada',
},
];
My Dropdown code is this,
body: Column(
children: [
DropdownSearch<String>(
mode: Mode.MENU,
items: countries['name'],
showSearchBox: true,
label: "Menu mode",
hint: "country in menu mode",
onChanged: (value){
print(countries['name']);
},
selectedItem: "Canada",
),
],
),
Here items: countries['name'] line i getting error as The argument type 'String' can't be assigned to the parameter type 'int'. Also when i select a country i want to print the country id. eg: if i select country as japan then it should print 4 in console. My Code is not working.
First of all, a List of Map doesn't work like this -> (countries['name]), try replace your items to:
DropdownSearch<String>(
mode: Mode.MENU,
items: countries.map((e)=>e['name']).toList(),
showSearchBox: true,
label: "Menu mode",
hint: "country in menu mode",
onChanged: (value){
print(value);
},
selectedItem: "Canada",
),
Try below code hope its help to you.
Refer my answer here for put json data to dropdown
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownSearch<dynamic>(
mode: Mode.MENU,
items: countries.map((e) => e['name']).toList(),
showSearchBox: true,
label: "Menu mode",
hint: "country in menu mode",
onChanged: (value) {},
selectedItem: "Canada",
),
),
Your result screen->
you have to create a data class Country and override the toString function to return the country name.
and update your dropdownSearch like this:
//don't forget to generate the list of countries frop the map
DropdownSearch<Country>(
mode: Mode.MENU,
items: yourCountries,
showSearchBox: true,
label: "Menu mode",
hint: "country in menu mode",
onChanged: (Country value){
print(value.id);
},
selectedItem: Country("Canada",7),
),
use your own country Model like this
DropdownSearch<Country>(
mode: Mode.MENU,
items: yourCountries,
popupProps: PopupProps.dialog(
showSelectedItems: false,
showSearchBox: true,
),
showSearchBox: true,
label: "Menu mode",
hint: "country in menu mode",
itemAsString: (Country u) => u.name,
onChanged: (Country country){
print(country.name);
print(country.id);
},
selectedItem: Country("Canada",7),
),
don't forget to use -> itemAsString field
//OR
you can Visit the - https://pub.dev/packages/dropdown_search#customize-showed-field-itemasstring. section from the package it self

The argument type 'Book' can't be assigned to the parameter type 'Map<String, dynamic>'.dart(argument_type_not_assignable)

actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextButton(
onPressed: () {
_bookCollectionReference.add(Book(
userId: FirebaseAuth.instance.currentUser.uid,
title: book.title,,
author: book.author,
photoUrl: book.photoUrl,
publishedDate: book.publishedDate,
description: book.description,
pageCount: book.pageCount,
categories: book.categories,
));
},
child: Text('Save')),
),
///class book
Map<String, dynamic> toMap() {
return {
'title': title,
'user_id': userId,
'author': author,
'notes': notes,
'photo_url': photoUrl,
'published_date': publishedDate,
'description': description,
'page_count': pageCount,
'categories': categories,
};
}
}
You forgot to convert you Dart Class to Map (json) by calling .toMap()
Try the following code inside your onPressed method:
_bookCollectionReference.add(
Book(
userId: FirebaseAuth.instance.currentUser.uid,
title: book.title,,
author: book.author,
photoUrl: book.photoUrl,
publishedDate: book.publishedDate,
description: book.description,
pageCount: book.pageCount,
categories: book.categories,
).toMap(),
);

Getting Error on implementing Dismissible on flutter list

I am trying to implement Dismissible to swipe and remove the item from the list in flutter, but I am getting the below error on implementation of the same
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of
type 'String'
at this line of the code key: Key(item)
How should I resolve it ?
ListView.separated(
separatorBuilder: (context, index){
return Divider();
},
controller: _scrollController,
itemCount: noteItems,
shrinkWrap: true,
itemBuilder: (context, index) {
final item = firstdata[index];
return
Dismissible(
direction: DismissDirection.endToStart,
key: Key(item),
onDismissed: (direction) {
setState(() {
firstdata.removeAt(index);
});
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text("$item dismissed")));
},
background: Container(color: Colors.red)
,
child: Padding(
padding: const EdgeInsets.fromLTRB(8.0, 7.0, 8.0, 0.0),
child: Column(
children: <Widget>[
ListTile(
leading:ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.asset('images/appstore.png', width: 50, height: 50)
) ,
title:
Row(children: [
Flexible(
child: firstdata[index]['id']!= null?AutoSizeText(
firstdata[index]['id'],
maxLines: 2,
style: TextStyle(fontWeight: FontWeight.bold),) :Text(''),
),
],),
),
],
),
),
);
},
),
The JSON data structure for the list view is here below
{
"error": "false",
"notification": [
{
"rn": "1",
"id": "224",
"company_details": {
"code": "2",
}
},
{
"rn": "2",
"id": "219",
"company_details": {
"code": "3",
}
},
{
"rn": "3",
"id": "213",
"company_details": {
"code": "3",
}
},
{
"rn": "4",
"id": "209",
"company_details": {
"code": "4",
}
},
{
"rn": "5",
"id": "204",
"company_details": {
"code": "3",
}
},
{
"rn": "6",
"id": "199",
"company_details": {
"code": "3",
}
},
{
"rn": "7",
"id": "193",
"company_details": {
"code": "3",
}
}
],
}
How should I implement the same and get it resolved?
As stated in the other answer, the Key function expects a string to create a key based on that. If you can identify an item based on one of its parameters (for example id), then you could use item.id and it would be fine.
However, to make sure it will be truly unique key for any combination of parameters (in your case id, rn and company_details) you can use ObjectKey:
Replace the following line:
key: Key(item)
With the following:
key:ObjectKey(item)
This way Flutter can identify your item's parameters and create a key based on the combination of them.
Other options include ValueKey and UniqueKey.
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
means that it crashed because it was expecting a String and flutter did not find one.
This means that:
key: Key(item)
Key(item)-> Is not a String. I don´t know how are you creating Key/where is it.
My best guess is to try to find some method like...:
`key: Key(item).aMethodthatgivesaString()`
`key: Key(item).toString()`
Let me know if this was useful.