Encoding / decoding complex Json in Flutter - arrays

I am going to use a real json. First of all, I should run the project that is written in Flask, then use the local host to achieve data.
Here is the real Json I`m using
{
"devices":[
{
"device_desc":"cooler",
"device_title":"cooler",
"functions":[
{
"device_id":1,
"function_desc":"pomp",
"function_title":"pomp",
"status":1
},
{
"device_id":1,
"function_desc":"less",
"function_title":"less",
"status":1
},
{
"device_id":1,
"function_desc":"up",
"function_title":"up",
"status":1
}
],
"image_path":"fdfdfsf",
"status_id":1,
"statuss":{
"status_desc":"device is on",
"status_title":"on"
}
},
{
"device_desc":"panke",
"device_title":"panke",
"functions":[
{
"device_id":2,
"function_desc":"less",
"function_title":"pomp",
"status":2
},
{
"device_id":2,
"function_desc":"less",
"function_title":"less",
"status":2
}
],
"image_path":"vfx",
"status_id":2,
"statuss":{
"status_desc":"device is off",
"status_title":"off"
}
}
]
}
This is my code:
these are data models for defining json properties:
class Base{
//the type of our object is the array
List<Device> _devices;
Base(this._devices);
List<Device> get devices => _devices;
set devices(List<Device> value) {
_devices = value;
}
}
class Device {
String _device_desc,_device_title,_image_path;
int _status_id;
List<function> _functions;
List<Status> _statuss ;
Device(this._device_desc, this._device_title, this._image_path,
this._status_id, this._functions, this._statuss);
List<Status> get statuss => _statuss;
set statuss(List<Status> value) {
_statuss = value;
}
List<function> get functions => _functions;
set functions(List<function> value) {
_functions = value;
}
int get status_id => _status_id;
set status_id(int value) {
_status_id = value;
}
get image_path => _image_path;
set image_path(value) {
_image_path = value;
}
get device_title => _device_title;
set device_title(value) {
_device_title = value;
}
String get device_desc => _device_desc;
set device_desc(String value) {
_device_desc = value;
}
}
class Status {
String _status_desc, _status_title;
Status(this._status_desc, this._status_title);
get status_title => _status_title;
set status_title(value) {
_status_title = value;
}
String get status_desc => _status_desc;
set status_desc(String value) {
_status_desc = value;
}}
class function {
String _function_desc, _function_title;
int _device_id, _status;
function(this._function_desc, this._function_title, this._device_id,
this._status);
get status => _status;
set status(value) {
_status = value;
}
int get device_id => _device_id;
set device_id(int value) {
_device_id = value;
}
get function_title => _function_title;
set function_title(value) {
_function_title = value;
}
String get function_desc => _function_desc;
set function_desc(String value) {
_function_desc = value;
}}
and this is the stateful class :
class MyHomePage extends StatefulWidget {
var title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<Base> _getBase() async {
var data = await http.get(Uri.encodeFull("http://192.168.1.111:5000/mobile-home"));
var jsonData = json.decode(data.body);
Base base = Base(jsonData);
return Base(jsonData[0]);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: Container(
child: FutureBuilder(
future: _getBase(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text("Loading..."),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.devices.length,
itemBuilder: (BuildContext context, int index) {
snapshot.data.devices.map<Widget>((devices){
return ListTile(
subtitle: Text(devices[index].device_desc.toString()),
title: Text(devices[index].device_title),
/*leading: CircleAvatar(
// ignore: argument_type_not_assignable
backgroundImage: NetworkImage(snapshot.data[index].thumbnailUrl),
)*/
);
}
);
},
);
}
},
),
),
);
}
}
I got an error when while debugging:
"type 'List<dynamic>' is not a subtype of type 'List<Device>'"
I can not get the data from json.

There was no question in your question, but I assume the question is:
My Json code is not working - How do I efficiently parse and encode complex json objects in my
flutter program.
For complex JSON you may want to consider using code generation to reduce the boiler plate you have to write. The flutter page has a good example using JsonSerializable. Here the basic instructions for your example:
Add dependencies to pubspec.yaml and run flutter pub get in the command line:
dependencies:
json_annotation: ^1.2.0
dev_dependencies:
build_runner: ^1.0.0
json_serializable: ^1.5.1
Create the basic Object model (similar to what you have done). Except for the following differences:
You don't have a List of Status for the field statuss, but a single Status object.
Don't use private fields.
To enable json boiler plate code generation do the following three steps:
add the json-annotations to each class,
add a factory .fromJson method on each class and
add a .toJson method on each class:
#JsonSerializable()
class Base {
List<Device> devices;
Base({this.devices});
factory Base.fromJson(Map<String, dynamic> json) => _$BaseFromJson(json);
Map<String, dynamic> toJson() => _$BaseToJson(this);
}
#JsonSerializable()
class Device {
String device_desc,device_title,image_path;
int status_id;
List<function> functions;
Status statuss ;
Device(this.device_desc, this.device_title, this.image_path,
this.status_id, this.functions, this.statuss);
factory Device.fromJson(Map<String, dynamic> json) => _$DeviceFromJson(json);
Map<String, dynamic> toJson() => _$DeviceToJson(this);
}
#JsonSerializable()
class Status {
String status_desc, status_title;
Status(this.status_desc, this.status_title);
factory Status.fromJson(Map<String, dynamic> json) => _$StatusFromJson(json);
Map<String, dynamic> toJson() => _$StatusToJson(this);
}
#JsonSerializable()
class function {
String function_desc, function_title;
int device_id, status;
function(this.function_desc, this.function_title, this.device_id,
this.status);
factory function.fromJson(Map<String, dynamic> json) => _$functionFromJson(json);
Map<String, dynamic> toJson() => _$functionToJson(this);
}
Run the command line to start code generation in the project root folder:
flutter packages pub run build_runner watch
Now an additional source file appears with your generated boiler plate code. Add this file to your own source file using the part keyword, for example if your source file is main.dart add the following line:
part 'main.g.dart';
And you are done - This is all you need to test your encoding / decoding. For example with the following code:
import 'dart:convert';
void main() => (){
var jsonExample = '{"devices": [{"device_desc": "cooler", "device_title": "cooler", "functions": [{"device_id": 1, "function_desc": "pomp", "function_title": "pomp", "status": 1}, {"device_id": 1, "function_desc": "less", "function_title": "less", "status": 1}, {"device_id": 1, "function_desc": "up", "function_title": "up", "status": 1}], "image_path": "fdfdfsf", "status_id": 1, "statuss": {"status_desc": "device is on", "status_title": "on"}}, {"device_desc": "panke", "device_title": "panke", "functions": [{"device_id": 2, "function_desc": "less", "function_title": "pomp", "status": 2}, {"device_id": 2, "function_desc": "less", "function_title": "less", "status": 2}], "image_path": "vfx", "status_id": 2, "statuss": {"status_desc": "device is off", "status_title": "off"}}]}';
Map base_example = json.decode(jsonExample);
Base base_example_parsed = Base.fromJson(base_example);
var numberDevices = base_example_parsed.devices.length;
var numberFuncs = base_example_parsed.devices[0].functions.length;
print('$base_example_parsed has $numberDevices devices and the first device has $numberFuncs functions');
var base_example_encoded_again = json.encode(base_example_parsed);
print('$base_example_encoded_again');
};
For more information please refer to:
1. the official example.
2. this blog.

There's a very good article about how to parse complex JSON in Flutter. Here's a quick summary...
Simple Stuff:
{
"id":"487349",
"name":"Pooja Bhaumik",
"score" : 1000
}
becomes...
class Student{
String studentId;
String studentName;
int studentScores;
Student({
this.studentId,
this.studentName,
this.studentScores
});
factory Student.fromJson(Map<String, dynamic> parsedJson){
return Student(
studentId: parsedJson['id'],
studentName : parsedJson['name'],
studentScores : parsedJson ['score']
);
}
}
You create a new Student object like Student.fromJson(your_parsed_json).
Sub-objects work in a similar way. For each object inside the parent object you make a new Dart object, each with it's own parser for fromJson. Then inside the parent factory you call that fromJson method (like so)... This also works for lists of objects.
factory Student.fromJson(Map<String, dynamic> parsedJson){
return Student(
studentId: parsedJson['id'],
studentName : parsedJson['name'],
studentScores : Teacher.fromJson(parsedJson['teacher'])
);

Related

Flutter does not output all the results during a post request

Flutter does not output all the results during a post request. Out of about 260 comes to the list, 113 are saved.
...............................................................................................................................................................................................................
Future<List<NewChatModel>> getAllChats({#required String userId}) async {
final response = await http.post(
Uri.parse(URL),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, int>{
'first_user_id': int.parse(userId),
}),
);
if (response.statusCode == 200) {
List<NewChatModel> returnList = [];
for (var i in jsonDecode(response.body)) {
returnList.add(NewChatModel.fromJson(i));
}
print(returnList.length);
return returnList;
} else {
return null;
}
}
class NewChatModel {
String id;
String chatId;
String messageId;
String message;
String messageDate;
String schoolId;
String fullName;
String phone;
String email;
String urlProfileImage;
String birthday;
String roleId;
String lastActivity;
String isOnline;
NewChatModel(
{this.id,
this.chatId,
this.messageId,
this.message,
this.messageDate,
this.schoolId,
this.fullName,
this.phone,
this.email,
this.urlProfileImage,
this.birthday,
this.roleId,
this.lastActivity,
this.isOnline});
factory NewChatModel.fromJson(dynamic json) {
return NewChatModel(
id: json['id'].toString(),
chatId: json['chat_id'].toString(),
messageId: json['message_id'].toString(),
message: json['message'].toString(),
messageDate: json['message_date'].toString(),
schoolId: json['school_id'].toString(),
fullName: json['full_name'].toString(),
phone: json['phone'].toString(),
email: json['email'].toString(),
urlProfileImage: json['urlProfileImage'].toString(),
birthday: json['birthday'].toString(),
roleId: json['role_id'].toString(),
lastActivity: json['last_activity'].toString(),
isOnline: json['is_online'].toString(),
);
}
}
Edit: added NewChatModel code
But I don`t think that its help solve problem
I think problem in String limit, idk
If at all it helps you, I have a list of chat conversations in my app, too. I collect them with a Stream and display them with a StreamBuilder(). This is a very resource efficient way to do it, without the need to actually collect all the conversations at once! The StreamBuilder() widget makes sure it collects only the conversations that are currently visible on the screen (plus some).
This is what it looks like:
import 'package:my_giggz/firebase_labels.dart';
import 'package:my_giggz/my_firebase.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class MyMessagesScreen extends StatefulWidget {
#override
_MyMessagesScreenState createState() {
return _MyMessagesScreenState();
}
}
class _MyMessagesScreenState extends State<MyMessagesScreen> {
String myUid = MyFirebase.authObject.currentUser!.uid;
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
// Stream of all the conversations in the database that contain my uid:
stream: MyFirebase.storeObject.collection(kCollectionConversations).where(kFieldParticipantsArray, arrayContains: myUid).orderBy(kFieldLastTimeStamp, descending: true).snapshots(),
builder: (context, asyncSnapshot) {
List<Widget> convCards = [];
QuerySnapshot? foundConversations = asyncSnapshot.data;
if (foundConversations != null) {
//It always wants to be null at first, and then I get errors for calling on null.
for (QueryDocumentSnapshot conv in foundConversations.docs) {
Map<String, dynamic> convData = conv.data() as Map<String, dynamic>;
convCards.add(
ConvCard(convData) // A homemade widget that takes a Map argument to display some data from the conversation
);
// i++;
}
} else {
// For as long as the found conversations are null, a spinner will be shown:
return Center(child: CircularProgressIndicator());
}
// This part will only be reached if conversations were found:
return ListView.builder(
padding: EdgeInsets.all(0),
itemCount: convCards.length,
itemBuilder: (context, index) {
return convCards[index];
},
);
},
),
);
}
}
If you have any questions on that, I'm happy to answer.
I do not know why this is so, but here is the answer to my question :)
For some reason, he doesn't want to show the entire length of the list, but he filled it out absolutely correctly)

Flutter: How to pass array data from json Future< to Widget

Being new to flutter, I'm learning and stumbling on the go.
I am trying to pass an array that I have received from json into an already waiting widget structure but can't quite seem to get the connection.
Here's the sample code:
class Products extends StatefulWidget {
#override
_ProductsState createState() => _ProductsState();
}
class _ProductsState extends State<Products> {
#override
void initState() {
_getProducts();
}
Future<List<Single_prod>> _getProducts() async {
var url = "";
var data = await http.get(url);
var jsonData = json.decode(data.body) as Map<String, dynamic>;
//print(jsonData.toString());
//jsonData.forEach((k, v) => print("Key : $k, Value : $v"));
List<Single_prod> items = [];
jsonData.forEach((k, v){
Single_prod item = Single_prod(v["error"], v["id"], v["name"], v["price"], v["image"]);
items.add(item);
});
//print(items.length);
return items; <---Tring to pass this to Widget build but not recognized.....
}
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: items.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index){
return Single_prod(
prod_err: items[index]['error'], <--- This items array is not recognized
prod_id: items[index]['id'],
prod_name: items[index]['name'],
prod_price: items[index]['price'],
prod_image: items[index]['image'],
);
});
}
}
The items array is not recognized in the widget
Here is the rest of the code:
class Single_prod extends StatelessWidget {
final prod_err;
final prod_id;
final prod_name;
final prod_price;
final prod_image;
Single_prod({
this.prod_err,
this.prod_id,
this.prod_name,
this.prod_price,
this.prod_image,
});
#override
Widget build(BuildContext context) {
return Card(
child: Hero(
tag: prod_name,
child: Material(
child: InkWell(
onTap: () => Navigator.of(context).push(new MaterialPageRoute(
// here we are passing the values of the products to the details page
builder: (context) => new ProductDetails(
prod_detail_name: prod_name,
prod_detail_image: prod_image,
prod_detail_id: prod_id,
prod_detail_price: prod_price,
))),
child: GridTile(
footer: Container(
height: 40.0,
color: Colors.white70,
child: ListTile(
leading: Text(prod_name, style: TextStyle(fontWeight: FontWeight.bold),),
title: Text(
prod_price,
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.w800, fontSize: 12),
),
/*subtitle: Text(
prod_oldprice,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w800, fontSize: 11, decoration: TextDecoration.lineThrough),
),*/
),
),
child: Image.asset(prod_image,
fit: BoxFit.cover,),
),
),
),
),
);
}
}
How does the upper code connect with the lower code?
Thanks in advance.
First, look at the scope of your 'items' variable: it is defined in getItems() function, and it is not visible outside the function. So, first thing: make it class level property.
Next - your initState will call your method. Method is async, and the way to handle it in initState to use '.then' on the Future returned by your method. What you want to do here is: once the future completes, you want to set your class level variable to hold the value returned by _getProduct() function.
And finally - this is very important to understand: you don't call build method yourself - flutter framework does it for you. Now, flutter does not have a magic way of knowing when you changed the data - it won't observe your code, so you need to tell it somehow that your state object changed, and it requires rebuild. You do it by calling setState() function.
I think you have another issue here actually: you already bulit your Single_prod widget in _getProduct(), no need to build it again. I tried to correct this also.
Try this (I didn't compile it so it might have few errors):
class Products extends StatefulWidget {
#override
_ProductsState createState() => _ProductsState();
}
class _ProductsState extends State<Products> {
List<Single_prod> items = [];
#override
void initState() {
super.initState();
_getProducts().then( (result) {
setState(() {
items=result;
}
});
}
Future<List<Single_prod>> _getProducts() async {
var url = "";
var data = await http.get(url);
var jsonData = json.decode(data.body) as Map<String, dynamic>;
//print(jsonData.toString());
//jsonData.forEach((k, v) => print("Key : $k, Value : $v"));
List<Single_prod> items = [];
jsonData.forEach((k, v){
Single_prod item = Single_prod(v["error"], v["id"], v["name"], v["price"], v["image"]);
items.add(item);
});
//print(items.length);
return items;
}
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: items.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index){
return items[index];
});
}
}

Flutter firebase, how to retrive user data and have it on the map or a list

I saw many examples on internet, but in each case, the data is returning on a listview. I don't want to print in a listview. I want to use data in the app.
This is the way I am addind data on firebase. (I am using a class Info).
void infouser(context) async {
final db = FirebaseFirestore.instance;
final info = Info(yourname, animaName, yourmail);
final uid = await Provider.of(context).auth.getCurrentUID();
await db.collection("userData").doc(uid).collection("info").add(info.toJson());
}
I also tried with set,
createInfo(context) async {
final uid = await Provider.of(context).auth.getCurrentUID();
DocumentReference documentReference =
await FirebaseFirestore.instance.collection('Animal').doc(uid);
Map<String, dynamic> todos = {
'name': yourname,
'animalname' :animalName,
'email' : yourmail,
};
documentReference.set(todos).whenComplete(() {
print( yourname, animalName, yourmail
);
});
}
In both case, I was only able to print data on a Listview. But that is not what I want. I want to have data on a list or a map to be able to use it elsewhere in the app.
Please, I if you have a link(or give me a example of code) where I can see example, it will be appreciate.
thank you.
This is the example of retrieving data as map from firestore:
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
}
I advise to use https://firebase.flutter.dev/docs/firestore/usage/? documentation when working with Firebase from flutter

convert array to be displayed in the list

I tried to display the output of this data into a list but it can't
this is my data output
{activity: {"project":" Distributions","code":2000,"code_name":"OpenProcessSnapshot","activity":{"id_process_snapshot":988,"name":"Android Process"}}, created_at: 2019-06-20 08:58:48.492885+07, id: 1, id_user: 1}
{activity: {"project":"Distributions","code":2000,"code_name":"OpenProcessSnapshot","activity":{"id_process_snapshot":988,"name":"Android Process"}}, created_at: 2019-06-20 08:58:48.492885+07, id: 1, id_user: 1}
{activity: {"project":" Distributions","code":2000,"code_name":"OpenProcessSnapshot","activity":{"id_process_snapshot":988,"name":"Android Process"}}, created_at: 2019-06-20 08:58:48.492885+07, id: 1, id_user: 1}
and this is my code
FutureBuilder(
future: UserController.getActivity(_selectedUser),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(snapshot.data.toString());
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(snapshot.data.toString()),
],
);
} else {
return Center(
child: Text("No data displayed"),
);
}
return Center(
child: CircularProgressIndicator(),
);
},
),
what if I want to display created_at and project?
You can use jsonDecode to get that specific element.
Documentation Link
For your case you have to create a new widget function and return it:
//put this method before your widget build function
Widget _mapJsonDataToText(String data){
Map<String, List<dynamic>> jsonData = jsonDecode(data);
Map<String, dynamic> jsonDataInner = jsonDecode(jsonData['activity']);
return Text(jsonDataInner['created_at']);
//do the same for project
}
children: <Widget>[
//gets the method that returns the text widget
_mapJsonDataToText(snapshot.data.toString()),
],
I have a different method, this will add up the data into the list. Not using future builder, just making use of my common sense to display the data logically into the list.
Assuming you know about http of flutter, if you don't then this is the link for you: Fetch data from the internet
Suppose you have a data[], in which activity{} are being displayed in your JSON output.
List<String> project = [];
List<String> createdAt = [];
void initState(){
super.initState();
//this will run this method on call of this page, everytime
this.fetchData();
}
Future<void> fetchData() async{
List<String> _project = [];
List<String> _createdAt = [];
final response =
await http.get('your_api_url');
//looping through the array of activity object
(response['data'] as list).forEach((item){
//check if the data comes correct
print(item['activity']['project']);
print(item['created_at']);
_project.add(item['activity']['project']);
_createdAt.add(item['created_at']);
});
setState((){
this.project = _project;
this.createdAt = _createdAt;
});
}
//In order to show them in the list of project, call ListView()
List<Widget> projectWidget(){
List<Widget> _widget = [];
this.project.forEach((item){
_widget.add(item);
});
return _widget;
}
//In order to show them in the list of createdAt, call ListView()
List<Widget> createdAtWidget(){
List<Widget> _anotherWidget = [];
this.createdAt.forEach((item){
_anotherWidget.add(item);
});
return _anotherWidget;
}
Display the data as you want in your UI. Let me if it works for you. Thanks :)

How to filter the values of my Observable?

I'm learning about observables atm and I have a question. I get a json array from my backend api and put it in an Observable (where image is my own defined model). Now these are all the images but I only want those whose name starts with display. I've tried a few things but I can't find the solution. This is what I've got so far.
get images$(): Observable<Image[]> {
return this._fetchImages$
.pipe(
filter(i => i.filter(img => img.name.toLowerCase().startsWith("display")))
);
}
this gives:
Type 'Image[]' is not assignable to type 'boolean'.ts(2322)
filter.d.ts(3, 46): The expected type comes from the return type of this signature.
Image model class
export class Image {
constructor(
private _name: string,
private _iso: string,
private _shutter: string,
private _aperture: string,
private _country: string,
private _likes: number,
private _content: string
) {}
get name(): string {
return this._name;
}
get iso(): string {
return this._iso;
}
get shutter(): string {
return this._shutter;
}
get aperture(): string {
return this._aperture;
}
get country(): string {
return this._country;
}
get likes(): number {
return this._likes;
}
get content(): string {
return this._content;
}
set likes(value: number) {
this._likes = value;
}
static fromJson(json: any): Image {
return new Image(
json.name,
json.iso,
json.shutterSpeed,
json.aperture,
json.country,
json.likes,
json.content
);
}
}
The service that provides me with the values
export class ImageDataService {
constructor(private http: HttpClient) {}
get images$(): Observable<Image[]> {
return this.http
.get(`${environment.apiUrl}/images/`)
.pipe(map((list: any[]): Image[] => list.map(Image.fromJson)));
}
}
the component that asks for the observable
export class GridComponent implements OnInit {
public countryFilter: string;
public filterImage$ = new Subject<string>();
private _fetchImages$: Observable<Image[]> = this._imageDataService.images$;
constructor(private _imageDataService: ImageDataService) {
this.filterImage$
.pipe(
distinctUntilChanged(),
debounceTime(400),
map(val => val.toLowerCase())
)
.subscribe(val => (this.countryFilter = val));
}
get images$(): Observable<Image[]> {
return this._fetchImages$.pipe(
map(i => i.filter(img => img.name.toLowerCase().startsWith('display')))
);
}
ngOnInit() {}
}
<div>
<mat-form-field>
<input matInput placeholder="Country" type="text" #countryName (keyup)="filterImage$.next($event.target.value)"
class="browser-default">
</mat-form-field>
<mat-grid-list cols="3" gutterSize=" 5px" rowHeight="500px">
<mat-grid-tile *ngFor="let image of (images$ | async)">
<app-image [image]="image"></app-image>
</mat-grid-tile>
</mat-grid-list>
</div>
export class ImageComponent implements OnInit {
private _icon: string;
#Input('image') public image: Image;
constructor() {
this._icon = 'favorite_border';
}
ngOnInit() {}
like() {
if (this._icon === 'favorite_border') {
this._icon = 'favorite';
this.likes++;
} else {
this._icon = 'favorite_border';
this.image.likes--;
}
console.log(this._icon);
}
get icon(): string {
return this._icon;
}
set icon(value: string) {
this._icon = value;
}
get iso(): string {
return this.image.iso;
}
get aperture(): string {
return this.image.aperture;
}
get shutterspeed(): string {
return this.image.shutter;
}
get country(): string {
return this.image.country;
}
get name(): string {
return this.image.name;
}
get content(): string {
return this.image.content;
}
get likes(): number {
return this.image.likes;
}
set likes(value: number) {
this.image.likes = value;
}
}
I get 10 json objects sent to me:
{
"id": 1,
"name": "Header",
"iso": "ISO-200",
"shutterSpeed": "1/80 sec",
"aperture": "f/5.6",
"country": "Belgium",
"content": //a base64 string
}
{
"id": 2,
"name": "Parallax1",
"iso": "ISO-100",
"shutterSpeed": "1/200 sec",
"aperture": "f/10",
"country": "Italy",
"content": another base64 string
}
{
"id": 5,
"name": "Display1",
"iso": "ISO-100",
"shutterSpeed": "1/200 sec",
"aperture": "f/10",
"country": "Italy",
"content": another base64 string
}
Now the major difference between the images is the name:
I've got 1 header, 3 Parallaxes and 6 Display images. I now want to filter that whay I get only the Display images. Basically: 10 images come in ---> 6 come out
Kind regards
I think you should change filter for map, like this:
.pipe(
map(
i => i.filter(
img => img.name.toLowerCase().startsWith("display")
)
)
);
I've moved the mapping to the class where I get them using a HttpClient instead of trying to filter them in my component. It works without querystring now.
code:
export class ImageDataService {
constructor(private http: HttpClient) {}
get images$(): Observable<Image[]> {
return this.http
.get(`${environment.apiUrl}/images/`)
.pipe(
map((list: any[]): Image[] => list.map(Image.fromJson)),
map(imgs =>
imgs.filter(img => img.name.toLowerCase().startsWith('display'))
)
);
}
}

Resources