mergeTemplateAndState method

  1. @protected
void mergeTemplateAndState(
  1. WidgetNodeSpec spec,
  2. Map template,
  3. Map state,
  4. Map parentContext,
)

Sanitizes the properties of a spec using template and string evaluation. E.g.: a property valued "${state.firstName}" will have its value replaced with the state's "firstName" key value.

Implementation

@protected
void mergeTemplateAndState(
    WidgetNodeSpec spec, Map template, Map state, Map parentContext) {
  properties.evaluateMap(spec.props, parentContext);
  var newTemplate = template.clone();
  properties.evaluateMap(newTemplate, parentContext);

  // Use Template to set Property values, if not existing
  mergeMaps(spec.props, newTemplate);

  // Set Widget's value via its alias
  var alias = spec.props["alias"] ?? spec.id;
  if (state.containsKey(alias)) {
    spec.props["value"] = state[alias];
  } else if (spec.props.containsKey("value")) {
    state[alias] = spec.props["value"];
  }

  // Evaluate State keys starting with Widget's Id
  for (var key in state.keys) {
    if (key.startsWith("${spec.id}.")) {
      var prop = key.replaceFirst("${spec.id}.", "");
      var value = state[key];
      dynamic evaluatedValue;
      if (value is Map) {
        evaluatedValue =
            properties.evaluateValue(value.clone(), parentContext);
      } else if (value is List<Map>) {
        evaluatedValue =
            properties.evaluateValue(value.clone(), parentContext);
      } else {
        evaluatedValue = properties.evaluateValue(value, parentContext);
      }
      spec.props[prop] = evaluatedValue;
      if (value is Map || value is List<Map>) {
        // Since we don't know where the key belongs, we'll set it in all Spec Maps
        // Only properties should be evaluated in build-time
        spec.widgets[prop] = value;
        spec.actions[prop] = value;
      }
    }
  }
}