Dart get class property value dynamically

Issue

I have a Class YearlyReportArchive, I want to be able to read the value of a single month dynamically and also add all the months and return the sum.

Is there a better solution than what I came up with?

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:mbpt/utils/tools/validate_double.dart';

class YearlyReportArchive {
  final double jan;
  final double feb;
  final double mar;
  final double apr;
  final double may;
  final double jun;
  final double jul;
  final double aug;
  final double sep;
  final double oct;
  final double nov;
  final double dec;

  YearlyReportArchive(
      {required this.jan,
      required this.feb,
      required this.mar,
      required this.apr,
      required this.may,
      required this.jun,
      required this.jul,
      required this.aug,
      required this.sep,
      required this.oct,
      required this.nov,
      required this.dec});

  double monthlyTotal(String monthName) {
    switch (monthName) {
      case 'jan':
        return jan;
      case 'feb':
        return feb;
      case 'mar':
        return mar;
//...
      default:
        return 0.00;
    }
  }

  double yearlyTotal() {
    return jan +
        feb +
        mar +
        apr +
        may +
        jun +
        jul +
        aug +
        oct +
        sep +
        nov +
        dec;
  }

  factory YearlyReportArchive.fromDoc(DocumentSnapshot doc) {
    Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
    return YearlyReportArchive(
        jan: validateDouble(data['jan']),
        feb: validateDouble(data['feb']),
        mar: validateDouble(data['mar']),
        apr: validateDouble(data['apr']),
        may: validateDouble(data['may']),
        jun: validateDouble(data['jun']),
        jul: validateDouble(data['jul']),
        aug: validateDouble(data['aug']),
        sep: validateDouble(data['sep']),
        oct: validateDouble(data['oct']),
        nov: validateDouble(data['nov']),
        dec: validateDouble(data['dec']));
  }
}

Solution

First you can create an enumerated type to support your months:

enum Months {
  january, february, march, april //...// , december
}

These months have a string representation (e.g. jan). To represent them, you can create a constant map, or a extension on your enumerated type:

  • Creating a constant map:
Map<Months, String> monthStrings = {
 Months.january: "jan",
 Months.february: "feb",
 Months.march: "mar",
 Months.april: "apr"
};
extension monthName on Months {

  String get name {
    switch (this) {
      case Months.january:
        return 'jan';
      case Months.February:
        return 'feb';
      default:
        return "";
    }
  }
}

This way you can access these values on your class, for example:

  • On your doubles, you can have a single map that associates each month with it’s value:
class YearlyReportArchive {
Map<Months, double> values;
}
  • Whenever you need to sum all you can use a for:
double answer = 0;
 for (double value in values.values){
   answer += value;
 }
  • When you need the string representation, access the Map you made or the extension method:
print(monthStrings[Months.january]);
var m = Months.january;
print(m.name());

You could also create a class that holds all these methods and definitions, but the general concept would be the same.

Answered By – Naslausky

Answer Checked By – Jay B. (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.