Line data Source code
1 : import 'package:flutter/widgets.dart'; 2 : import 'package:json_schema_document/json_schema_document.dart'; 3 : 4 : class FlutterJsonSchemaFormController { 5 3 : FlutterJsonSchemaFormController({this.textEditingControllerMapping}); 6 : Map<String, dynamic> data = {}; 7 : Map<String, dynamic>? initialState = {}; 8 : Function(Map<String, dynamic>)? onChanged; 9 : 10 : /// If null, the form inner state will be unaccessible. 11 : Map<String, dynamic>? textEditingControllerMapping = {}; 12 : 13 : /// Create or update a value of the key on the specified path. 14 1 : void updateValue(List<String> path, String value) { 15 2 : print('value: $value // path: $path'); 16 : 17 2 : String? updater = path.isNotEmpty ? path.last : null; 18 : 19 : // get the index of the last element 20 2 : int updaterIndex = path.length - 1; 21 : 22 : // print("updater is $updater. It's index is $updaterIndex"); 23 : 24 : if (updater != null) { 25 : // For each path element, we need to go one level deeper in the data map 26 : // and then update the value. 27 : var last = "0"; 28 : 29 2 : for (var i = 0; i <= updaterIndex; i++) { 30 1 : final p = path[i]; 31 : 32 : // case 0: the first element can be a value or a object 33 1 : if (i == 0) { 34 : // if this case is the last case, then we need to update the value 35 1 : if (updaterIndex == 0) { 36 : // update the value on the data field 37 2 : data[p] = value; 38 : // update or create the controller 39 2 : if (textEditingControllerMapping?[p] is TextEditingController) { 40 0 : (textEditingControllerMapping?[p] as TextEditingController).text = 41 : value; 42 1 : } else if (textEditingControllerMapping?[p] == null) { 43 1 : textEditingControllerMapping?[p] = 44 0 : TextEditingController(text: value); 45 : } 46 : 47 : // if this case isn't the last case, then we need to create de object 48 : } else { 49 2 : if (data[p] == null) { 50 : // create the object 51 3 : data[p] = {}; 52 : } 53 : last = p; 54 : } 55 : // case 1: the second element only can be a value in this especific situation 56 : } else { 57 3 : data[last]?[p] = value; 58 : // update or create the controller 59 1 : if (textEditingControllerMapping?[last]?[p] 60 1 : is TextEditingController) { 61 0 : (textEditingControllerMapping?[last]?[p] as TextEditingController) 62 0 : .text = value; 63 1 : } else if (textEditingControllerMapping?[last]?[p] == null) { 64 1 : textEditingControllerMapping?[last]?[p] = 65 0 : TextEditingController(text: value); 66 : } 67 : } 68 : } 69 : } 70 : } 71 : 72 : /// Sets the value of both the instances of textEditingController on the 73 : /// textEditingControllerMapping map and the data map. 74 2 : void setData(Map<String, dynamic> newData, 75 : [Map<String, dynamic>? newTextEditingControllerMapping]) { 76 : // final listOfKeys = newData.keys.toList(); 77 : 78 : if (newTextEditingControllerMapping == null) { 79 2 : newTextEditingControllerMapping = textEditingControllerMapping; 80 2 : data = newData; 81 : } 82 : 83 : // newTextEditingControllerMapping ??= textEditingControllerMapping; 84 : 85 4 : for (final key in newData.keys) { 86 6 : if (newTextEditingControllerMapping?[key] is Map && newData[key] is Map) { 87 3 : setData(newData[key], newTextEditingControllerMapping?[key]); 88 : } else { 89 4 : (newTextEditingControllerMapping?[key] as TextEditingController).text = 90 2 : newData[key]; 91 : } 92 : } 93 : 94 : // for (final entry in newData.entries) { 95 : // final correspondingValueOnTextEditingControllerMapping = 96 : // textEditingControllerMapping?[entry.key]; 97 : // if (correspondingValueOnTextEditingControllerMapping 98 : // is TextEditingController) { 99 : // correspondingValueOnTextEditingControllerMapping.text = entry.value; 100 : // } 101 : // if (correspondingValueOnTextEditingControllerMapping is Map) { 102 : // setData(newData[entry.key] as Map<String, dynamic>); 103 : // } 104 : // } 105 : } 106 : 107 : // void setTextEditingControllers(Map<String, dynamic> newData) { 108 : // // recursively set the value on the textEditingControllerMapping map 109 : // for (var entry in data.entries) { 110 : // // if the value is a map, then we need to recursively set the value on the 111 : // // ... 112 : // if (entry.value is Map && 113 : // textEditingControllerMapping?[entry.key] is Map) { 114 : // setTextEditingControllers(entry.value); 115 : // } 116 : // // else, we need to set the value on the textEditingControllerMapping map 117 : // else { 118 : // (textEditingControllerMapping?[entry.key] as TextEditingController?) 119 : // ?.text = entry.value; 120 : // } 121 : // } 122 : // } 123 : } 124 : 125 : /// Takes as an argument a [JsonSchema] and return a Map<String, dynamic> where 126 : /// the keys are the names of the properties and the values are instances of 127 : /// [TextEditingController] for the corresponding properties on the 128 : /// FlutterJSONSchemaForm or similar maps on recursive fashion 129 2 : Map<String, dynamic> generateEditingControllerMapping(JsonSchema jsonSchema) { 130 : // for each property on the JSON Schema 131 6 : return jsonSchema.properties.map((key, value) { 132 : // if the property is an object 133 4 : if (value.type == JsonSchemaType.object) { 134 : // if the property is an object, then we need to create a map with the 135 : // same name and the same type of the object 136 2 : return MapEntry(key, generateEditingControllerMapping(value)); 137 : } else { 138 : // if the property is a value, then we need to create a controller 139 4 : return MapEntry(key, TextEditingController()); 140 : } 141 : }); 142 : }