List returnMovies = [];
Future<List> _getData() async {
final response = await http.get("https:../getTodayMovies",
headers: {HttpHeaders.AUTHORIZATION: Acess_Token.access_token});
if (response.body != null) {
returnMovies = json.decode(response.body);
.....
setState(() {});
} else {
final responseUpcoming = await http.get("/upcoming",
headers: {HttpHeaders.AUTHORIZATION: Acess_Token.access_token});
returnMovies = json.decode(responseUpcoming.body);
}
The response.body looks like:
[{"id":394470548,"host_group_name":"heyab redda","movie_image":"..png","type":"horror","code":"X123","name":"Lovely","start_time":1554364800,"end_time":1554393600,"}]
The responseUpcoming.body looks like:
{"id":394470545,"host_group_name":"foo redda","movie_image":".png","type":"horror","code":"X123","name":"Lovely","start_time":1554364800,"end_time":1554393600,"}, {"id":394470548,"host_group_name":"foo1 redda","movie_image":"..png","type":"comic","code":"X125","name":"Lovely1","start_time":1554364800,"end_time":1554393600,"}
The error I get is: String, dynamic is not a subtype of type List<dynamic>.
In the first API call that I am doing I normally get in return an array of objects, however, when this is empty, the second API call returns a list of objects that I want to push into the array called returnMovies, how can I achieve this?? Is there any way to .push these objects in the array?? So then I want to use this array to build dynamically a Listview.builder.
Also is it correct the way I am declaring it? I am quite new on Dart. Thank you
Sounds like you are looking for addAll
returnMovies.addAll(json.decode(returnUpcoming.body))
I will suggest to use
returnMovies.addAll({your object here})
When you do this json.decode(response.body) you are getting a List of Map you should use List<dynamic> movieListData and get the items like this:
movieListData = json.decode(response.body);
returnMovies = movieListData.map((dynamic movieData) {
String id = movieData['_id'];
String host_group_name = movieData['host_group_name'];
String duration = movieData['duration'];
return new Movie(id,title, duration);
}).toList();
Related
In mongoose, there's the timestamp: true option to a schema, which auto-populates a createdAt and updatedAt for any model item added.
Is there something similar in Aqueduct?
If not, how do I manually do so?
I currently tried this, which is failing, as usual:
#Operation.post()
Future<Response> createICD(#Bind.body() ICD body) async {
body.createdAt = DateTime.now();
final query = Query<ICD>(context)..values = body;
final insertICD = await query.insert();
return Response.ok({'state': true, 'data': insertICD});
}
Error from the above approach is:
Converting object to an encodable object failed: Instance of 'ICD'
It's failing when you send the response; you need to call asMap() on insertICD. The response body object you are providing is a standard Dart map - it doesn't have any special encoding behavior, so it doesn't know how to encode a complex type like ManagedObject. Invoke asMap() on the managed object to convert it to a standard Dart map:
#Operation.post()
Future<Response> createICD(#Bind.body() ICD body) async {
body.createdAt = DateTime.now();
final query = Query<ICD>(context)..values = body;
final insertICD = await query.insert();
return Response.ok({'state': true, 'data': insertICD.asMap()});
}
Also, see http://aqueduct.io/docs/db/validations/#update-and-insert-callbacks for setting timestamps at create/update events.
I am trying to get a value from firestore and save it to a variable in flutter. I tried using StreamBuilder, but since i am not building a widget it does not work.
To clarify my problem, I am trying to get a url from a firestore document and then open it when i press a button in the app.
I also tried to adapt code i found in another question, but that returns null.
Future _getUrl() async{
DocumentReference docRef = Firestore.instance.collection('information').document('pdf');
var data;
docRef.get().then((datasnapshot){
data = datasnapshot.data['url'];
});
return data;
}
The collection is called information, the document pdf, and the field url
This method will return null because you are not waiting for the get() future to return before you return data. docRef.get() is a Future, so it will execute asychronously. Meanwhile, your program will move on to the next line, which is return data.
Something like this would do what you want I think:
Future _getUrl() async{
DocumentReference docRef = Firestore.instance.collection('information').document('pdf');
return docRef.get().then((datasnapshot){
return datasnapshot.data['url'];
});
}
Since _getUrl is already marked as async you can also use await in its body to return the right value:
Future _getUrl() async {
DocumentReference docRef = Firestore.instance.collection('information').document('pdf');
await datasnapshot = docRef.get();
let data = datasnapshot.data['url'];
return data;
}
I have this method, which compiles with no problems in Dart 2. However at run-time I get the following error
type 'List<dynamic>' is not a subtype of type 'List<ExchangeRate>'
As you see in the code I create and return new ExchangeRate objects within .map() and then after that I return a rateEntries.toList() which I expect to be of type List<ExchangeRate>, however it seems to be inferred as type List<dynamic>!!!
#override
Future<List<ExchangeRate>> getExchangeRatesAt(DateTime time, Currency baseCurrency) async {
final http.Client client = http.Client();
final String uri = "some uri ...";
return await client
.get(uri)
.then((response) {
var jsonEntries = json.decode(response.body) as Map<String, dynamic>;
var rateJsonEntries = jsonEntries["rates"].entries.toList();
var rateEntries = rateJsonEntries.map((x) {
return new ExchangeRate(x.value.toDouble());
});
return rateEntries.toList(); // WHY IS IT RETURNING A List<dynamic> here?
})
.catchError((e) => print(e))
.whenComplete(() => client.close());
}
However if I cast it specifically to ExchangeRate it would be fine.
return rateEntries.toList().cast<ExchangeRate>();
This casting at the end seems redundant to me, why should I need it?
Well, it seems that the cast is necessary to fully define the type.
But, you can avoid the cast if you add any of the following snippets:
Give the correct type to the rateJsonEntries variable
List<dynamic> rateJsonEntries = jsonEntries["rates"].entries.toList();
For whatever reason this works in my case.
Add the parameter type to the map() method
var rateEntries = rateJsonEntries.map<ExchangeRate>((x) {
return new ExchangeRate(x.value.toDouble());
});
I would like to know how to define the data type and how to return the object (record) using getObject(). Currently, the only way that I have been able to use the result (record) outside of the function that obtains it is to call another function with the result. That way, the data-type does not need to be specified. However if I want to return the value, I need to define the data-type and I can't find what it is. I tried "dynamic" but that didn't appear to work. For example ":
fDbSelectOneClient(String sKey, Function fSuccess, String sErmes) {
try {
idb.Transaction oDbTxn = ogDb1.transaction(sgTblClient, 'readwrite');
idb.ObjectStore oDbTable = oDbTxn.objectStore(sgTblClient);
idb.Request oDbReqGet = oDbTable.getObject(sKey);
oDbReqGet.onSuccess.listen((val){
if (oDbReqGet.result == null) {
window.alert("Record $sKey was not found - $sErmes");
} else {
///////return oDbReqGet.result; /// THIS IS WHAT i WANT TO DO
fSuccess(oDbReqGet.result); /// THIS IS WHAT i'm HAVING TO DO
}});
oDbReqGet.onError.first.then((e){window.alert(
"Error reading single Client. Key = $sKey. Error = ${e}");});
} catch (oError) {
window.alert("Error attempting to read record for Client $sKey.
Error = ${oError}");
}
}
fAfterAddOrUpdateClient(oDbRec) {
/// this is one of the functions used as "fSuccess above
As someone else once said (can't remember who), once you start using an async API, everything needs to be async.
A typical "Dart" pattern to do this would be to use a Future + Completer pair (although there's nothing inherently wrong with what you've done in your question above - it's more a question of style...).
Conceptually, the fDbSelectOneClient function creates a completer object, and the function returns the completer.future. Then, when the async call completes, you call completer.complete, passing the value in.
A user of the function would call fDbSelectOneClient(...).then((result) => print(result)); to make use of the result in an async way
Your code above could be refactored as follows:
import 'dart:async'; // required for Completer
Future fDbSelectOneClient(String sKey) {
var completer = new Completer();
try {
idb.Transaction oDbTxn = ogDb1.transaction(sgTblClient, 'readwrite');
idb.ObjectStore oDbTable = oDbTxn.objectStore(sgTblClient);
idb.Request oDbReqGet = oDbTable.getObject(sKey);
oDbReqGet.onSuccess.listen((val) => completer.complete(oDbReqGet.result));
oDbReqGet.onError.first.then((err) => completer.completeError(err));
}
catch (oError) {
completer.completeError(oError);
}
return completer.future; // return the future
}
// calling code elsewhere
foo() {
var key = "Mr Blue";
fDbSelectOneClient(key)
.then((result) {
// do something with result (note, may be null)
})
..catchError((err) { // note method chaining ..
// do something with error
};
}
This future/completer pair only works for one shot (ie, if the onSuccess.listen is called multiple times, then the second time you will get a "Future already completed" error. (I've made an assumption on the basis of the function name fDbSelectOneClient that you are only expecting to select a single record.
To return a value from a single future multiple times, you'll probably have to use the new streams feature of the Future - see here for more details: http://news.dartlang.org/2012/11/introducing-new-streams-api.html
Note also, that Futures and Completers support generics, so you can strongly type the return type as follows:
// strongly typed future
Future<SomeReturnType> fDbSelectOneClient(String sKey) {
var completer = new Completer<SomeReturnType>();
completer.complete(new SomeReturnType());
}
foo() {
// strongly typed result
fDbSelectOneClient("Mr Blue").then((SomeReturnType result) => print(result));
}
I have some code that checks a parameter and the calls a peer method to get me items from the DB.
What I need to get is these items in JSON.
My peer method is like:
public static function searchFromRequest($word)
{
$c = new Criteria();
$c->addJoin(self::ARTICLE_ID, ArticlePeer::ID);
$c->add(self::TITLE, '%'.$word.'%', Criteria::LIKE);
$c->addAnd(self::ARTICLE_ID, null, Criteria::ISNOTNULL);
$c->addAscendingOrderByColumn(self::TITLE);
return self::doSelect($c);
}
and my action is:
public function executeSearch()
{
$this->word = $this->getRequestParameter('word');
$this->content_type = $this->getRequestParameter('content_type');
if($this->content_type == 'article')
{
$words = ItemPeer::searchFromRequest($this->word);
}
else
{
echo "Nothing here";
}
I can var_dump($words) and I get an array (collection) of items. The problem is, how do I return all of the items in JSON?
I've tried using:
$this->getResponse()->setHttpHeader('Content-type', 'application/json');
$words = ItemPeer::searchFromArticleRequest($this->word);
return $this->renderText(json_encode($words));
But this just returns loads of empty JSON brackets: [{},{},{},{},{},{},{},{},{},{},{},{},{},{}]
Thanks
It seems that json_encode() doesn't like the way Propel Objects are built.
Another solution could be forcing Propel to returnin basic associative objects, using XXXPeer::doSelectStmt()
public static function searchFromRequest($word, $returnPropelObjects = true)
{
$c = new Criteria();
$c->addJoin(self::ARTICLE_ID, ArticlePeer::ID);
$c->add(self::TITLE, '%'.$word.'%', Criteria::LIKE);
$c->addAnd(self::ARTICLE_ID, null, Criteria::ISNOTNULL);
$c->addAscendingOrderByColumn(self::TITLE);
if ($returnPropelObjects)
return self::doSelect($c);
$stmt = self::doSelectStmt($c);
$results = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$results[] = $row;
}
return $results;
}
Propel 1.6:
object->toJSON();
collection->exportTo('JSON');
The json_encode/json_decode can only encode/decode PHP arrays not objects. The variable
$words
will be an array of Item objects, that's why the output you wrote.
There are basically two solutions. You write your own json encoder that works for objects, like the first comment here:
http://php.net/manual/en/function.json-encode.php
or you write a function that converts your Item objects into PHP arrays like here:
http://www.phpro.org/examples/Convert-Object-To-Array-With-PHP.html
You could also call toArray() on your objects.
$words = ItemPeer::searchFromArticleRequest($this->word);
$wordsArray = array();
foreach ($words as $word)
{
$wordsArray[] = $word->toArray();
}
return $this->renderText(json_encode($wordsArray));
Propel 1.6 will have a toJSON() method for the individual objects or for a whole collection of objects.