Transferring data from a Query to a variable - dart

Hello I'm developing an App but it stopped because I have a problem that I'm going to explain it:
I made a Login screen to my app located in main.dart file. In this file I do a query to my server using a PHP file using JSON to encode the query and in the dart file i use the Json.decode to validate the data.
Now the question is how can I put that data in a variable to use it in another Widget? What I'm trying to do is putting the name and the email from the query to my side-bar menu which is my HomePage Widget.
Dart:
class LoginStates extends State<Login>{
#override
Widget build(BuildContext context) {
TextEditingController user=new TextEditingController();
TextEditingController pass=new TextEditingController();
Future<List> _login() async{
final response =await
http.post("https://exclinico.com/admin/FlutterClases/login.php", body: {
"correo": user.text,
"password": pass.text,
});
print(response.body);
var datosusuario = json.decode(response.body);
if (datosusuario.length==0) {
Mensaje(context);
}
else{
Navigator.pushReplacementNamed(context, '/mainpage');
}
}
PHP:
<?php
include("conexion.php");
$usuario=$_POST['correo'];
$contraseña=$_POST['password'];
$contraseña=base64_encode($contraseña);
$query=$conexion->query("SELECT*FROM paciente WHERE correo_elect = '$usuario' AND password='$contraseña'");
$resultado=array();
while($fetchData=$query->fetch_assoc()){
$resultado[]=$fetchData;
}
$_SESSION['correo'] = $usuario;
echo json_encode($resultado);
?>
I need to transfer the name and email to HomePage. Sorry for the English BTW! Thanks.

Related

When scrolling up in listview, first item keeps re-render

I'm experiencing an annoying thing, where the first item in my listview keeps re-render, when scrolling up. Even if I'm at the top.
only way i noticed this, was because I have a widget, that on load, fetches an url, and get the meta title, description and image, and displaying it in a nice card.
My listviews are fairly simple:
ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
itemCount: model.posts.posts.length,
itemBuilder: (context, index) {
// Items goes here
});
How do I stop it from happening?
The widget that keeps re-rendering, is a stateless widget that imports a ScopedModel model, that fetches some data from the internet, and scraped for meta data, and then updated the model.
#override
Widget build(BuildContext context) {
UrlEmbedModel _model = new UrlEmbedModel(); // <-- the ScopedModel
_model.fetchHtml(url); // <-- the url param comes from the constuctor
// Rest of the widget
}
Here is the code that fetches content from the net.
void fetchHtml(url) {
http.get(url).then((response) {
if (response.statusCode == 200) {
// If server returns an OK response, parse the JSON
var document = parse(response.body);
var list = document.getElementsByTagName('meta');
for (var item in list) {
if (item.attributes['property'] == "og:title") {
_title = item.attributes['content'];
}
if (item.attributes['property'] == "og:description") {
_description = item.attributes['content'];
}
if (item.attributes['property'] == "og:image") {
_imageUrl = item.attributes['content'];
}
notifyListeners();
}
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load post');
}
});
}
The code you wrote, seems OK, but what about the function that makes the request? Can you show it?
If it's a Future function, it'll only make a request once and then finish it, it's not like a stream function that will be always listening to an event.
EDIT
First of all, if this functions makes a request, then, the type of the functions must be Future, void type if don't return anything, after that, add the async call. You could change the .then method to an await method, it'll suit you better.
Future<void> fetchHtml(url) async {
final Response response = await get(url);
final dynamic documents = json.decode(response.body); //import 'dart:convert';
print(documents); // print to see what you get than, pass it to the variables you want the data
if (response.statusCode == 200) {
//in here
}
}
I can see a feel things in the fetch request, I'd be glad if you answer it:
Why you're not deserializing the json you receiving?
var documents = json.decode(response.body)
You could print the documents variable after deserializing it and atribute it to the widgets you want
The way you're doing it it's not wrong, but could improve it.
Found the culprit.
The issue wasn't the listview, it was the RefreshIndicator that I used.
As soon I removed it, the issue went away.
This seems to be a bug with Widget.

Flutter - Fetch data of 'DateTimePickerFormField' value using controller

I am a flutter beginner and trying to write an app.
For 'TextFormField' widget, we can get its value using the 'TextEditingController' like below,
TextEditingController titleController = TextEditingController();
.
.
.
expTitle = titleController.text;
Is there a simillar way to get the value from 'DateTimePickerFormField' widget using controller ? Currently I pick the value via 'onChanged' property of DateTimePickerFormField like below
onChanged: (dt) => setState(() => datePicked = dt)
you can use TextEditingController for DateTimePickerFormField

Implement GraphQL & Flutter

Is there a way to implement GraphQL in flutter?
I was trying making the API call with the query and variables objects in a JSON object.
type '_InternalLinkedHashMap' is not a subtype of type 'String' in type cast
I have been using graphql_flutter package for a few weeks now and it seems to work well enough. Here is an example:
import 'package:graphql_flutter/graphql_flutter.dart' show Client, InMemoryCache;
...
Future<dynamic> post(
String body, {
Map<String, dynamic> variables,
}) async {
final Client client = Client(
endPoint: endpoint,
cache: new InMemoryCache(),
);
final Future<Map<String, dynamic>> result =
client.query(query: body, variables: variables);
return result;
}
To use just give it the graphql and any variables. i.e. a delete mutation may look like
String deleteMutation =
'''mutation deleteItem(\$itemId: ID!) {
deleteItem(input: { itemId: \$itemId}) {
itemId
}
}'''.replaceAll('\n', ' ');
await post(deleteMutation , variables: <String, dynamic>{'itemId': itemId});
This is updated and working solution of #aqwert
import 'package:graphql_flutter/graphql_flutter.dart';
...
HttpLink link = HttpLink(uri: /*your url here*/); // you can also use headers for authorization etc.
GraphQLClient client = GraphQLClient(link: link as Link, cache: InMemoryCache());
QueryOptions query = QueryOptions(
document:
r'''
mutation deleteItem($id: String!) {
deleteItem(callId: $id)
}
''',
variables: {'id' : id}
);
var result = await client.query(query);

How to pass object or list of objects in the Fluro or Flutter route navigator?

I have used Fluro package inside my Flutter app, and I implemented all of my routes with a handler like the example of this package.
Could you please let me know what is the correct way to pass an object or list of objects between routes?
You could do that via ModalRoute.of(context).settings.arguments
so if you have object:
class ScreenArguments {
final String title;
ScreenArguments(this.title);
}
navigate with:
Navigator.of(context).pushNamed("/screen", arguments: ScreenArguments("Title"));
and in handler:
static Handler _screenHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
final ScreenArguments args = ModalRoute.of(context).settings.arguments;
return PassArgumentsScreen(args?.title);
});
The solution presented at How to pass JSON response to another view works unless your object has a string (or the decoded JSON contains) a / as #Chirag said.
I'm giving my solution as it worked, since my object has an URL inside.
Given the router:
_router.define("/groups/:group", handler: Handler(handlerFunc: (context, params) {
String param = params["group"][0];
GroupAPIModel group = GroupAPIModel.fromJson(decodeJsonDataForFluro(param));
return GroupDetailsScreen(group);
}));
Defining:
String encodeJsonDataForFluro(Map<String, dynamic> mapToEncode) {
return jsonEncode(mapToEncode).replaceAll("/", HtmlEscape().convert("/"));
}
Map<String, dynamic> decodeJsonDataForFluro(String encodedMap) {
return jsonDecode(encodedMap.replaceAll(HtmlEscape().convert("/"), "/"));
}
This method would reach that route:
void _onGroupClicked(GroupAPIModel group) {
String bodyJson = encodeJsonDataForFluro(group.toJson());
router.navigateTo(context: context, path: "/groups/$bodyJson");
}
Just struggled with this and found a solution. You can do this:
Object object = <Your Object>
Navigator.of(context).pushNamed("/page/" + object.id.toString(),
arguments: object);
And then access the custom object in Fluro like this:
static void setupRouter() {
router.define("page/:pageId", handler: _pageHandler);
}
static Handler _pageHandler =
Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
Object object = ModalRoute.of(context).settings.arguments;
return Widget(object);
});
While Fluro doesn't have this, this is a solution that isn't completely terrible.
I used to pass the data as an encoded JSON and String format like all other solutions in this question. Recently, the Fluro plugin provides a way of pass arguments as a class object between the routes like a Flutter navigator.
After pushing a route with a custom RouteSettings you can use the BuildContext.settings extension to extract the settings. Typically this would be done in Handler.handlerFunc so you can pass RouteSettings.arguments to your screen widgets.
/// Push a route with custom RouteSettings if you don't want to use path params
FluroRouter.appRouter.navigateTo(
context,
'home',
routeSettings: RouteSettings(
arguments: MyArgumentsDataClass('foo!'),
),
);
/// Extract the arguments using [BuildContext.settings.arguments] or [BuildContext.arguments] for short
var homeHandler = Handler(
handlerFunc: (context, params) {
final args = context.settings.arguments as MyArgumentsDataClass;
return HomeComponent(args);
},
);
In the case of using the Flutter navigator instead of the Fluro plugin use this link or check the following approach.
The Navigator provides the ability to navigate to a named route from any part of an app using a common identifier. In some cases, you might also need to pass arguments to a named route. For example, you might wish to navigate to the /user route and pass information about the user to that route.
To pass different pieces of data, create a class that stores this information.
// You can pass any object to the arguments parameter.
// In this example, create a class that contains a customizable
// title and message.
class ScreenArguments {
final String title;
final String message;
ScreenArguments(this.title, this.message);
}
Now you need to define a handler using ModalRoute:
static Handler _screenHandler = Handler(
handlerFunc: (BuildContext context, Map<String, dynamic> params) {
final ScreenArguments args = ModalRoute
.of(context)
.settings
.arguments;
return PassArgumentsScreen(args?.title);
});
And navigate with:
Navigator.pushNamed(
context,
"/screen",
arguments: ScreenArguments(
'Class Arguments Screen',
'This message is extracted in the build method.',
),
);

Using Java Request Sampler inside a ForEach controller in Jmeter

I am Trying to use a Java request Sampler inside a ForEach Controller.
This is my custom Sampler
public class ClientSampler extends AbstractJavaSamplerClient {
String Name;
#Override
public Arguments getDefaultParameters() {
Arguments defaultParameters = new Arguments();
defaultParameters.addArgument("name", "Tarek");
return defaultParameters;
}
#Override
public void setupTest(JavaSamplerContext context) {
Name = context.getParameter("name");
}
#Override
public SampleResult runTest(JavaSamplerContext context) {
System.out.println(Name);
}
}
in Jmeter I create user defined variables with 5 variables:
And a ForEach Controller:
then added the java request as a child to ForEach controller:
the Test plan is the following:
when I start the test the output is:
first
first
first
first
first
expected:
first
second
third
fourth
fifth
even if I set the start and end indexes in the ForEach controller the result is the same.
using an http sampler inside the ForEach controller works great, but when using a Java requests the result is not as expected.
Can anyone explain why I am getting this output?
I solved it.
The problem is because I misunderstood how it works:
Jmeter calls SetupTest(JavaSamplerContext context) once before the Test starts and calls runTest(JavaSamplerContext context) in each loop (I though it calls SetupTest also at the beginning of each loop).
so I just added
Name = context.getParameter("name");
inside runTest and now the result is exactly how it should be.
#Override
public SampleResult runTest(JavaSamplerContext context) {
Name = context.getParameter("name");
System.out.println(Name);
}

Resources