简体   繁体   中英

Dart: Convert map (Key / Value) into an Ordered List[]

I'm receiving a document snapshot from firestore and I convert it into a Map<String, dynamic> and I know that maps are not ordered, however, I want to order the layout of my screen fields in a certain order. Problem is, the order that I want to achieve is not alphabetical. Here is a sample of my map:

Map<String, dynamic> customerInfo = {
  'projectName': 'John Doe',  
  'state': 'Arizona', 
  'city': 'Tempe',
  'estimate': 123000,
  'geoLocation': '12.345678,23.456789'
}

So, I am sending this map to a loop to iterate over keys/values and converting them into a list of widgets, however, for some screens I need to have 'State' be the first widget, and 'City' be the second widget, and vice versa for other screens. Some maps will have more fields, those extra fields will not matter later on, I just want to maintain a certain order for certain fields if they exist.

I tried looping over the keys using a switch / if to match the keys and do a List<Widget>().add(Text(key, value)) however, the generated list is still unordered obviously. Here is a sample code of what I am trying to achieve:

class ProjectViews {
  List<Widget> projectDetailedView(Map<String, dynamic> data) {
    final List<Widget> fields = [];
    fields.add(
      Text(
        data['projectName'],
        style: TextStyle(
          fontSize: 24,
          fontWeight: FontWeight.bold,
          color: constants.primaryTextColor,
        ),
        textAlign: TextAlign.start,
      ),
    );
    data.forEach((key, value) {
      if (key == 'state') {
        fields.add(dataField(key, value));
      } else if (key == 'city') {
        fields.add(dataField(key, value));
      } else if (key == 'estimate') {
        fields.add(dataField(key, value));
      }
      // switch (key) {
      //   case 'state':
      //     fields.add(dataField(key, value));
      //     break;
      //   case 'city':
      //     fields.add(dataField(key, value));
      //     break;
      //   case 'estimate':
      //     fields.add(dataField(key, value));
      //     break;
      // }
    });
    return fields;
  }

  Widget dataField(String key, dynamic value) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            key,
            style: TextStyle(fontSize: 20),
          ),
          Text(
            value.toString(),
            style: TextStyle(fontSize: 20),
          ),
        ],
      ),
    );
  }
}

I want to make sure the List<Widget> fields are added in a certain order. The received map may contain 5 elements or 20 elements, only some of those need to be in order.

Can I use a List<String> arranged as my preferred order and convert the map based on this list?

Any other options to achieve this please?

Thanks

Maybe you can use a LinkedHashMap . It keeps the key insertion order.

FirebaseFirestore has a.orderBy() function that you can use to order your data when you query a collection.

    QuerySnapshot<Map<String, dynamic>> snapshot = 
await firestoreInstance.collection('collectionName')
         .orderBy('value', descending: false)
        .get();

Note: Your question seems like you're trying to get a list of Customer Info from firebase, so all you have to do is replace the 'collectionName' in my code with the name of the customer info collection. This is a querysnapshot because it queries the collection and gets you all the customer info in the collection.

You will also have to replace the 'Value' in my code here with the key of the value you want it to be ordered with. You can also choose whether it should be ascending or descending by setting the descending value to either true or false.

I hope this helps.

So here is my solution to the problem, basically you create a new ordered map with only the field names that you want to display in the order of display, then you populate this new map with the data/widgets.

class ProjectViews {
  List<Widget> projectDetailedView2(Map<String, dynamic> data) {
    final List<Widget> fields = [];
    final Map<String, dynamic> orderedFields = {
      'state': '',
      'city': '',
      'geoLocation': '',
    };  // this map has the items we want to display in the order we want
    fields.add(
      Text(
        data['projectName'],
        style: TextStyle(
          fontSize: 24,
          fontWeight: FontWeight.bold,
          color: constants.primaryTextColor,
        ),
        textAlign: TextAlign.start,
      ),
    );
    data.forEach((key, value) {
      if (orderedFields.keys.contains(key)) {
        orderedFields[key] = dataField(key, value);
      }
    });
    orderedFields.forEach((key, value) {
      if (value.runtimeType == Widget) {
        fields.add(value);
      }
    });
    return fields;
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM