In the efforts of learning Flutter framework / Dart, I created a sample project.
I have a class called person.dart
with the following content:
class Person {
String personFirstName;
String personLastName;
Person(
{this.personFirstName, this.personLastName}
);
}
Next, I have a "builder" class, person_builder.dart
, where I create sample data of people:
import 'package:adv_search/model/person.dart';
class PersonDataBuilder {
List getPeople() {
return [
Person(
personFirstName: "John",
personLastName: "Smith"
),
Person(
personFirstName: "Alex",
personLastName: "Johnson"
),
Person(
personFirstName: "Jane",
personLastName: "Doe"
),
Person(
personFirstName: "Eric",
personLastName: "Johnson"
),
Person(
personFirstName: "Michael",
personLastName: "Eastwood"
),
Person(
personFirstName: "Benjamin",
personLastName: "Woods"
),
Person(
personFirstName: "Abraham",
personLastName: "Atwood"
),
Person(
personFirstName: "Anna",
personLastName: "Clack"
),
Person(
personFirstName: "Clark",
personLastName: "Phonye"
),
Person(
personFirstName: "Kerry",
personLastName: "Mirk"
),
Person(
personFirstName: "Eliza",
personLastName: "Wu"
),
Person(
personFirstName: "Jackey",
personLastName: "Lee"
),
Person(
personFirstName: "Kristin",
personLastName: "Munson"
),
Person(
personFirstName: "Oliver",
personLastName: "Watson"
),
];
}
}
I have added search functionality to the top navigation bar just fine... upon clicking the search icon, the search field opens up (within the top nav) allowing me to provide search input. I have a controller that has a listener, capturing user input just fine, as shown in my main.dart
file:
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:adv_search/model/person.dart';
import 'package:adv_search/data/person_builder.dart';
void main() => runApp(new AdvancedSearch());
class AdvancedSearch extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'List of People',
home: new ListPersonPage(title: 'List of People'),
);
}
}
class ListPersonPage extends StatefulWidget {
ListPersonPage({Key key, this.title}) : super(key: key);
final String title;
@override
_ListPersonPageState createState() => _ListPersonPageState();
}
class _ListPersonPageState extends State<ListPersonPage> {
List people;
TextEditingController controller = new TextEditingController();
String filter;
Widget appBarTitle = new Text("List of People");
Icon actionIcon = new Icon(Icons.search);
@override
void initState() {
PersonDataBuilder pdb = new PersonDataBuilder();
people = pdb.getPeople();
controller.addListener(() {
setState(() {
filter = controller.text;
});
});
super.initState();
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final appTopAppBar = AppBar(
elevation: 0.1,
title: appBarTitle,
actions: <Widget>[
new IconButton(
icon: actionIcon,
onPressed: () {
setState(() {
if (this.actionIcon.icon == Icons.search) {
this.actionIcon = new Icon(Icons.close);
this.appBarTitle = new TextField(
style: new TextStyle(
color: Colors.white,
),
decoration: new InputDecoration(
prefixIcon: new Icon(Icons.search, color: Colors.white),
hintText: "Search...",
hintStyle: new TextStyle(color: Colors.white)),
controller: controller,
);
} else {
this.actionIcon = new Icon(Icons.search);
this.appBarTitle = new Text("List of People");
}
});
},
),
],
);
ListTile personListTile(Person person) => ListTile(
title: Text(
person.personFirstName + " " + person.personLastName,
style: TextStyle(color: Colors.black45, fontWeight: FontWeight.bold),
),);
Card personCard(Person person) => Card(
child: Container(
decoration: BoxDecoration(color: Colors.grey[300]),
child: personListTile(person),
),
);
final appBody = Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: people.length,
itemBuilder: (BuildContext context, int index) {
//return filter == null || filter == "" ? personCard(people[index]) : people[index].contains(filter) ? personCard(people[index]) : new Container();
return filter == null || filter == "" ? personCard(people[index]) : new Container();
},
),
);
return Scaffold(
appBar: appTopAppBar,
body: appBody,
);
}
}
However, where I am stuck at, and seeking guidance, is in the ListView.builder
This is what I am currently returning in ListView.builder
(line 106)--
return filter == null || filter == "" ? personCard(people[index]) : people[index].contains(filter) ? personCard(people[index]) : new Container();
The error I am getting is:
NoSuchMethodError: Class 'Person' has no instance method 'contains'
Receiver: Instance of 'Person'
Tried calling: contains("John")
Currently, I cannot filter at all, given the error above. I would like to know:
- How can I allow a user to search by either first or last name and have the view refresh with the filtered cards of people found, based on user input?
- When I click on the search icon, the input field is not auto-focused... am I setting up my search functionality the correct way?
- Is there a better/recommended way to create the data (list of people)?
EDIT 1
I should add: Upon launch of the app, I can see a list of ALL people that were created through the builder class.
EDIT 2
Added ALL code files in their entirety; re-phrased parts of the post and added couple additional questions.