I am testing flutter graphql for first time. Here is my query and variables that I am using graphql explorer.
My question is before I pass the query and queryVariables, I need to replace 1001 in queryVariables with parameter value. May I know how I can replace it?
const String query = r'''
query Albums($where: AlbumWhereInput) {
albums(where: $where) {
id
title
artist {
name
}
}
}
''';
const String queryVariables = r'''
{
"where": {
"artist_id": 1001
}
}
''';
Future<QueryResult> performQuery(String query,
{required Map<String, dynamic> variables}) async {
QueryOptions options =
QueryOptions(document: gql(query), variables: variables);
final result = await _client.query(options);
return result;
}
You haven't specified what package you're using, so I can't be specific about what is the best way to do this. But generally, you can use something like string interpolation:
final artistId = 1001;
final queryVariables = '''
{
"where": {
"artist_id": $artistId
}
}
''';
Note how we're using a normal string using ''' and not a raw string (r''') to be able to interpolate via $.
Related
Looking for a clean way to parse out data from an API.
The API returns data for creating “Boat” and “Car” models wrapped up in metadata.
{
“timestamp” “0000”,
“data”: {
“count” “1”,
“results” [
{
“name”: “boatyMcBoatFace”
}
]
}
}
I want to create 2 classes for the metadata and also the boat/car data using custom fromJson() methods.
Current implementation is something like this
Class Boat {
String name;
Boat.fromJson(json) {
this.name = json[‘name’]
}
static List<Boat> listFromJson(List<dynamic> json) {
return json.map((c) => Boat.fromJson(c)).toList();
}
}
ResponseModel<T> {
String timestamp
DataModel data
ResponseModel.fromJson(json) {
this.timestamp = json[‘timestamp’]
this.data = DataModel<T>.fromJson(json[‘data’])
}
}
DataModel<T> {
String count
List<T> results
DataModel.fromJson(json) {
this.count = json[‘count’]
this.results = json[‘results’] // change this, see below
}
}
Currently I'm creating a ResponseModel, which in turn creates a DataModel.
But then I'm manually creating and setting Boats using:
// yes
final res = methodThatMakesHttpRequest();
final apiResponse = ResponseModel<Boat>.fromJson(res);
// no
final boats = Boat.listFromJson(apiResponse.data.results);
apiResponse.data.results = boats;
Ideally I would remove those last two lines, and instead have Boats get created dynamically within DataModel.fromJson with something like
DataModel.fromJson(json) {
this.count = json[‘count’]
T.listFromJson(json[‘results’])
}
But this of course does not work as T.listFromJson does not exist.
I integrated API, I want to get both key and value from API response. I stored both key and value in two separate arrays and display inside the listview.so How to get key and value from api response.
[
{ "Name": "abc"
"Department": "Marketing",
"EmpCode": "ABC123",
"Salary":"20000",
"Pincode": 100023
}]
I got response using this code:
List list = json.decode(response.body);
So how to get Name,department,empcode and abc,marketing separate.
just use a forEach loop and it will extract keys and values for you which you can store according to your requirement and you don't have to worry about how many keys you have
response.forEach((key, value){
print('key is $key');
print('value is $value ');
}
Create a class that will hold your fields and add a fromJson method like so:
class ClassName{
ClassName(
{this.Name,
this.Department,
this.EmpCode,
this.Salary,
this.Pincode,
});
String Name;
String Department;
String EmpCode;
double Salary;
String Pincode;
ClassName.fromJson(Map<String, dynamic> json) {
Name= json['Name'];
Department= json['Department'];
EmpCode= json['EmpCode'];
Salary= json['Salary'];
Pincode= json['Pincode'];
}
}
And then you could do something like that with your json that you get from the API:
var x = json.decode(response.body.toString());
var className = ClassName.fromJson(x);
Auto-complete search list
How to parse csv data instead of json data as mentioned in this article. I am new to csv and I have trouble mappping csv data to a model list. I need to pass the csv list to autocomplete field in another package plz help me in mapping it to the model.
class Players {
String keyword;
int id;
String autocompleteterm;
String country;
Players({
this.keyword,
this.id,
this.autocompleteterm,
this.country
});
factory Players.fromJson(Map<String, dynamic> parsedJson) {
return Players(
keyword: parsedJson['keyword'] as String,
id: parsedJson['id'],
autocompleteterm: parsedJson['autocompleteTerm'] as String,
country: parsedJson['country'] as String
);
}
}
class PlayersViewModel {
static List<Players> players;
static Future loadPlayers() async {
try {
players = new List<Players>();
String jsonString = await rootBundle.loadString('assets/players.json');
Map parsedJson = json.decode(jsonString);
var categoryJson = parsedJson['players'] as List;
for (int i = 0; i < categoryJson.length; i++) {
players.add(new Players.fromJson(categoryJson[i]));
}
} catch (e) {
print(e);
}
}
Example Code (Not working):
void main() {
List json = [
{
"sku": "SKU0001",
"uids": [
{
"uid": "U001"
}
]
}
];
var result = json.map( (item) {
item['no_desc'] = true; // able to add the key and bool value
item['uids'] = item['uids'].map( (uid) {
uid['is_scanned'] = true; // failed to add, but able to accept string value only.
return uid;
}).toList();
return item;
}).toList();
print(result);
}
return error 'bool' is not a subtype of type 'String'
Expected Result
[
{
sku: SKU0001,
no_desc: true,
uids: [
{
uid: U001,
is_scanned: true // must be boolean
}
]
}
]
It work when i try in String value.
uid['is_scanned'] = 'true';
How can I add bool value into the nested list?
If I am writing in javascript way,
it should be able to add the key into nested array ( list ).
But why in dart lang, it prompt me error?
Can someone expert in dart lang willing to explain to me?
Your issue can be fixed by creating a new Map instance in the inner .map method with the Map.from constructor.
item['uids'] = item['uids'].map( (uid) {
uid['is_scanned'] = true; // failed to add, but able to accept string value only.
return uid;
}).toList();
should be changed to:
item['uids'] = item['uids'].map( (uid) {
Map<String, dynamic> toReturn = Map.from(uid);
toReturn['is_scanned'] = true;
return toReturn;
}).toList();
I believe this issue is due to dart implicitly declaring the inner uids maps as Map<String, String> so creating a new instance changes this and allows you to assign any value to the keys of the Map.
Full working sample:
void main() {
List json = [
{
"sku": "SKU0001",
"uids": [
{
"uid": "U001"
}
]
}
];
var result = json.map( (item) {
item['no_desc'] = true;
item['uids'] = item['uids'].map( (uid) {
Map<String, dynamic> toReturn = Map.from(uid);
toReturn['is_scanned'] = true;
return toReturn;
}).toList();
return item;
}).toList();
print(result);
}
I couldn't find a way to store the Type value in Map so that I could use it in is operator to check the validity of type using this map later on. Also, can is operator accept Type as a variable?
For eg, Below is hypothetical code solving the problem but it's invalid.
Map<String, Type> map = {
"sku": String,
"price": double,
"quantity": int,
};
dynamic value = 10;
if(value is map["quantity"]){
print("value is of type int and int is expected for quantity value");
}
You can do something like this:
class TypeCheck<T> {
const TypeCheck();
bool typeCheck(dynamic value) => value is T;
}
void main() {
Map<String, TypeCheck> map = {
"sku": TypeCheck<String>(),
"price": TypeCheck<double>(),
"quantity": TypeCheck<int>(),
};
dynamic value = 10;
if (map["quantity"]!.typeCheck(value)) {
print("value is of type int and int is expected for quantity value");
}
}
Im not sure I fully understand I understand what you are trying to do but why don't you try something like.
bool _validate(Map productDetails){
if (productDetails.containsKey("sold_individually") && productDetails["sold_individually"] is bool) {
//return true or false
}
else if (productDetails.containsKey("stock_quantity") && productDetails["stock_quantity"] is int){
//return true or false
}
else if (productDetails.containsKey("tax_class") && productDetails["tax_class"] is String && productDetails["tax_class"].isNotEmpty) {
//return true or false
} else {
//return true or false
}
}
As for the other part of your question you wont get an error but you will always return false. In contrast if you check if a variable is dynamic it will always return true.
I don't really understand your end goal. But from what you have, I don't think you are taking advantage of the strongly-typed nature of dart.
Assuming you are getting your map from an API, you could enforce
typing manually in your code as follows;
Map<String, Type> map = {
"sku": json['key'] as String,
"price": json['key'] as double,
"quantity": json['key'] as int,
};
And avoid using dynamic when declaring variables.
OR
In the case you have a user-defined type you what to compare, you can use the equatable package on a class for instance as follows;
class CustomMap extends Equatable {
String sky;
double price;
int quantity;
// here you put the fields of a class you want for two instances of a class to be equal.
#overide
List<Object> get props => [sky, price, quantity];
}
Update from your comment
You should have a custom class for the API objects for instance;
class Item extends Equatable {
String sku;
double price;
int quantity;
Item({this.sky, this.price, this.quantity});
// factory constructor
factory Item.fromMap(Map<String, dynmic> json) {
final sku = json['sku'] as String,
final price = (json['price'] as num) as double,
final quantity = json['quantity'] as num,
return Item(sku: sku, price: price, quantity: quantity);
}
// define equatable objects
#override
List<Object> get props => [sku, price, quantity];
}
Now you can use it as follows;
Future<Item> objectsFromService(Map<String, dynamic> json ) async {
http.Response response = http.get(url);
if(response.status == 200) {
final decodedJson = json.decode(response.body);
return Item.fromJson(decodedJson);
}else{
print('Error fetch data');
return null;
}
}
Hope it helps