In my code shown here, I am trying to insert the row at the top. When I try to add the row at the bottom, I don't face any difficulty but when I try to insert the empty row at the top, it does create a row but it also has the data from the previous row. Here, I have tried to pass a local key and a uniqueKey()
.
Now, when I pass the inputFieldKey
, it creates a new row but it has the data from the previous row, although I am able to edit and enter data into the textfield normally.
When I pass uniqueKey()
, I am getting an empty row at the top as required but here the problem is, whenever I try to edit or enter any text into the textfield, it rebuilds the widget(which is correct) and with that is creates a new uniqueKey()
every time, so because of that the cursor gets disappear from textfield after every letter.
Like if I enter 's'
, the cursor will disappear and I'll have to go to the textfield and again point in textfield for next entering next letter.
What I want is, to create an empty row with normal behaviour (where I can add/edit text normally). So, as soon as I click the button, it will run the function addEmptyRow
, this will check for position, for top it will insert the row at the top. I have checked thoroughly, it is adding empty data properly.
This line is responsible for the behavior (I think) key:
widget.mode == FormType.add ? inputFieldKey : UniqueKey(),
Full code:
void addEmptyRow() {
int indexOfRow = rows.length; // Get the index of the new row
Map<String, dynamic> emptyData = {};
List<dynamic> columns = tableFieldDetails
.otherFieldProperties['table_configuration']['columns'];
String columnName = '';
for (int columnDetails = 0;
columnDetails < columns.length;
columnDetails++) {
var column = columns[columnDetails];
columnName = column['name'];
// Check if columnName exists in emptyData
if (!emptyData.containsKey(columnName)) {
emptyData[columnName] = ''; // Add columnName with empty value
}
}
if (newRowPosition == 'top') {
//need to come back to this logic, may be some other way
tableRecords.insert(0, emptyData);
rows.insert(0, buildSingleRow(0));
if (indexOfRow == 0) {
buildRows();
}
}
}
DataRow buildSingleRow(int tableRow) {
Map<String, dynamic> record = tableRecords[tableRow];
List<DataCell> cells = tableColumn.map<DataCell>((column) {
String columnName = column['name'];
String dataType = column['type'];
dynamic cellValue = record[columnName];
Map<String, dynamic> columnAccess = column['access'];
return DataCell(
SizedBox(
child: buildDataCell(
tableRow, dataTypecolumn, true,
cellValue: cellValue),
),
);
}).toList();
return DataRow(
cells: cells,
);
}
Widget buildDataCell(int indexOfRow, String dataType, key, columnAccess,
Map<String, dynamic> column, bool inputField,
{dynamic cellValue = ''}) {
Key inputFieldKey = Key('${column['name']}-$indexOfRow');
//Key inputFieldKeyForEdit = Key('${column['name']}-$indexOfRow' 'edit');
//if inputField is false, display row value as text
if (!inputField) {
return Center(child: Text(cellValue.toString()));
} else {
if (dataType == 'string') {
return Padding(
padding: const EdgeInsets.all(0.0),
child: TableTextInputFieldComponent(
column: column,
indexOfRow: indexOfRow,
value: cellValue,
isStrikeThrough: isStrikeThrough,
key: widget.mode == FormType.add ? inputFieldKey : UniqueKey(),
);
} else {
return const Center(child: Text('Not supported'));
}
}
}
inputFieldKey needs to be unique for every row in this case.
Initially, inputFieldKey will be let's say 0, then after inserting 1 more row to it, the inputFieldKey for 1st row will be again 0 and for 2nd row it'll be 1. So, even though the rows have distinct keys the problem is, apart from adding to row, the inputFieldKey is also shifting, like, 0 then 0,1, then 0,1,2, and so it is also taking the values along with it.
to resolve the problem the solution is to have distinct inputFieldKey
Key inputFieldKey = Key('${column['name']}-${tableRecords.length}');
instead of using both uniqueKey and inputFieldKey, it can be passed simply as key
key: inputFieldKey