多行编辑表格 Flutter

huangapple go评论65阅读模式
英文:

Multi-row editing table Flutter

问题

我在Flutter中尝试进行表格的多行编辑,找到了我需要的内容,但是它是用Javascript写的。我想知道在Flutter中是否有一种“简单”的方法来实现相同的功能。

我的Javascript示例:https://editor.datatables.net/examples/simple/multiRow

英文:

I'm struggling to do a multi row edit on a table in flutter, I found exactly what I need, but it's in Javascript. I wonder if there is an "easy" way to do the same thing in Flutter.

My example in Javascript: https://editor.datatables.net/examples/simple/multiRow

答案1

得分: 1

这是一个可编辑的表格小部件的代码。以下是代码的主要部分的翻译:

class EditableTable extends StatefulWidget {
  EditableTable({
    required this.rapport,
    required this.rapportIndex,
  });

  final rapport;
  final rapportIndex;

  @override
  _EditableTableState createState() => _EditableTableState();
}

class _EditableTableState extends State<EditableTable> {
  List<DataRow> rows = [];
  final ScrollController _scrollController = ScrollController();
  List<int> selectedLignes = [];
  bool tableauModifie = false;
  late List<Map<String, dynamic>> _tableau;

  void saveTable(List<Map<String, dynamic>> newTable, int rapportIndex) async {
    // 保存表格数据到 Firestore
  }

  @override
  void initState() {
    // 初始化表格数据
  }

  @override
  Widget build(BuildContext context) {
    // 构建用户界面
  }

  // 其他方法和小部件在这里...
}

这段代码是一个可编辑的表格小部件,可以用于显示和编辑表格数据。它包括了初始化数据、保存数据到 Firestore 和构建用户界面的部分。如果您需要进一步了解代码的具体功能,请随时提出问题。

英文:

I have made this code and this is working :), I don't know if it's ugly or not, but is that can help someone. I give no details but if someone have a question I'l try to awnser it :

class EditableTable extends StatefulWidget {
EditableTable({
required this.rapport,
required this.rapportIndex,
});
final rapport;
final rapportIndex;
@override
_EditableTableState createState() =&gt; _EditableTableState();
}
class _EditableTableState extends State&lt;EditableTable&gt; {
List&lt;DataRow&gt; rows = [];
final ScrollController _scrollController = ScrollController();
List&lt;int&gt; selectedLignes = [];
bool tableauModifie = false;
late List&lt;Map&lt;String, dynamic&gt;&gt; _tableau;
void saveTable(List&lt;Map&lt;String, dynamic&gt;&gt; newTable, int rapportIndex) async {
try {
final String rapportId = globals.gRapportEnCours![rapportIndex][&#39;id&#39;];
await FirebaseFirestore.instance
.collection(&quot;rapports&quot;)
.doc(rapportId)
.update({
&#39;tableau&#39;: newTable,
&#39;date_modification&#39;: DateTime.now(),
});
globals.gRapportEnCours![rapportIndex][&#39;tableau&#39;] = newTable;
} catch (e) {
print(&quot;Erreur lors de la sauvegarde du tableau: $e&quot;);
}
}
@override
void initState() {
super.initState();
_tableau = List&lt;Map&lt;String, dynamic&gt;&gt;.from(widget.rapport[&#39;tableau&#39;]);
rows = _tableau.asMap().entries.map&lt;DataRow&gt;((entry) {
int index = entry.key;
Map&lt;String, dynamic&gt; ligne = entry.value;
return DataRow(cells: [
DataCell(Text(ligne[&#39;N&#176; trou&#39;].toString())),
DataCell(TextFormField(
readOnly: widget.rapport[&#39;is_valid&#39;],
initialValue: ligne[&#39;Profondeur&#39;],
onChanged: (value) {
setState(() {
_tableau[index][&#39;Profondeur&#39;] = value;
tableauModifie = true;
});
saveTable(_tableau, widget.rapportIndex);
},
)),
DataCell(TextFormField(
readOnly: widget.rapport[&#39;is_valid&#39;],
initialValue: ligne[&#39;Inclinaison&#39;],
onChanged: (value) {
setState(() {
_tableau[index][&#39;Inclinaison&#39;] = value;
tableauModifie = true;
});
saveTable(_tableau, widget.rapportIndex);
},
)),
DataCell(TextFormField(
readOnly: widget.rapport[&#39;is_valid&#39;],
initialValue: ligne[&#39;N&#176; taillant&#39;],
onChanged: (value) {
setState(() {
_tableau[index][&#39;N&#176; taillant&#39;] = value;
tableauModifie = true;
});
saveTable(_tableau, widget.rapportIndex);
},
)),
DataCell(
TextFormField(
readOnly: widget.rapport[&#39;is_valid&#39;],
initialValue: ligne[&#39;Observation&#39;],
onChanged: (value) {
setState(() {
_tableau[index][&#39;Observation&#39;] = value;
tableauModifie = true;
});
saveTable(_tableau, widget.rapportIndex);
},
),
),
]);
}).toList();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
SingleChildScrollView(
controller: _scrollController,
child: Column(
children: [
SizedBox(
width: 800,
height: 540,
child: SingleChildScrollView(
child: Column(children: [
DataTable(
columns: [
DataColumn(
label: Text(&#39;N&#176; trou&#39;),
),
DataColumn(
label: Text(&#39;Profondeur&#39;),
),
DataColumn(
label: Text(&#39;Inclinaison&#39;),
),
DataColumn(
label: Text(&#39;N&#176; taillant&#39;),
),
DataColumn(
label: Text(&#39;Observation&#39;),
),
],
rows: rows.map&lt;DataRow&gt;((row) {
final index = rows.indexOf(row);
return DataRow(
selected: widget.rapport[&#39;is_valid&#39;]
? false
: selectedLignes.contains(index),
onSelectChanged: widget.rapport[&#39;is_valid&#39;]
? null
: (value) {
setState(() {
if (value!) {
selectedLignes.add(index);
} else {
selectedLignes.remove(index);
}
});
},
cells: row.cells,
);
}).toList(),
),
if (!widget.rapport[&#39;is_valid&#39;])
ElevatedButton(
onPressed: () =&gt; setState(() {
int newNumTrou = widget.rapport[&#39;tableau&#39;]
[widget.rapport[&#39;tableau&#39;].length - 1]
[&#39;N&#176; trou&#39;] +
1;
widget.rapport[&#39;tableau&#39;].add({
&#39;N&#176; trou&#39;: newNumTrou,
&#39;Profondeur&#39;: &#39;&#39;,
&#39;Inclinaison&#39;: &#39;&#39;,
&#39;N&#176; taillant&#39;: &#39;&#39;,
&#39;Observation&#39;: &#39;&#39;,
});
rows.add(
DataRow(
cells: List.generate(
5,
(index) =&gt; DataCell(
index == 0
? Text(&#39;$newNumTrou&#39;)
: TextFormField(
readOnly: widget.rapport[&#39;is_valid&#39;],
initialValue: &#39;&#39;,
),
),
),
),
);
}),
child: Text(&#39;Ajouter une ligne&#39;),
),
]),
),
),
],
),
),
if (!widget.rapport[&#39;is_valid&#39;])
Positioned(
right: 5.0,
child: FloatingActionButton(
onPressed: selectedLignes.isEmpty ? null : editSelectedLignes,
child: Icon(Icons.edit),
),
),
],
);
}
Map&lt;String, dynamic&gt; getCommonValues(List&lt;int&gt; selectedLignes) {
Map&lt;String, dynamic&gt; commonValues =
Map.from(_tableau[selectedLignes.first]);
for (int i = 1; i &lt; selectedLignes.length; i++) {
Map&lt;String, dynamic&gt; currentLigne = _tableau[selectedLignes[i]];
for (String key in commonValues.keys.toList()) {
if (commonValues[key] != currentLigne[key]) {
commonValues[key] = &#39;Valeurs multiples&#39;;
}
}
}
return commonValues;
}
void editSelectedLignes() {
// V&#233;rifie si des lignes sont s&#233;lectionn&#233;es
if (selectedLignes.isEmpty) {
showDialog(
context: context,
builder: (context) =&gt; AlertDialog(
title: Text(&#39;Aucune ligne s&#233;lectionn&#233;e&#39;),
content: Text(&#39;Veuillez s&#233;lectionner au moins une ligne &#224; &#233;diter.&#39;),
actions: [
ElevatedButton(
onPressed: () =&gt; Navigator.pop(context),
child: Text(&#39;OK&#39;),
),
],
),
);
} else {
Map&lt;String, dynamic&gt; commonValues = getCommonValues(selectedLignes) ??
{
&#39;Profondeur&#39;: &#39;&#39;,
&#39;Inclinaison&#39;: &#39;&#39;,
&#39;N&#176; taillant&#39;: &#39;&#39;,
&#39;Observation&#39;: &#39;&#39;,
};
// Ouvre la pop-up d&#39;&#233;dition
showDialog(
context: context,
builder: (context) =&gt; EditLignesDialog(
selectedLignes: selectedLignes,
tableau: _tableau,
saveTable: saveTable,
selectedLigneValues: commonValues,
rapportIndex: widget.rapportIndex,
),
).then((value) {
if (value != null &amp;&amp; value) {
// V&#233;rifiez si &#39;value&#39; est &#39;true&#39;
setState(() {
updateRows();
});
}
});
}
}
void updateRows() {
rows = List&lt;DataRow&gt;.generate(
_tableau.length,
(index) {
Map&lt;String, dynamic&gt; ligne = _tableau[index];
return DataRow(
cells: [
DataCell(
Text(&#39;${ligne[&#39;N&#176; trou&#39;]}&#39;),
),
DataCell(TextField(
enabled: !widget.rapport[&#39;is_valid&#39;],
controller:
TextEditingController(text: &#39;${ligne[&#39;Profondeur&#39;]}&#39;),
onChanged: (value) =&gt; ligne[&#39;Profondeur&#39;] = value)),
DataCell(TextField(
enabled: !widget.rapport[&#39;is_valid&#39;],
controller:
TextEditingController(text: &#39;${ligne[&#39;Inclinaison&#39;]}&#39;),
onChanged: (value) =&gt; ligne[&#39;Inclinaison&#39;] = value)),
DataCell(TextField(
enabled: !widget.rapport[&#39;is_valid&#39;],
controller:
TextEditingController(text: &#39;${ligne[&#39;N&#176; taillant&#39;]}&#39;),
onChanged: (value) =&gt; ligne[&#39;N&#176; taillant&#39;] = value)),
DataCell(TextField(
enabled: !widget.rapport[&#39;is_valid&#39;],
controller:
TextEditingController(text: &#39;${ligne[&#39;Observation&#39;]}&#39;),
onChanged: (value) =&gt; ligne[&#39;Observation&#39;] = value)),
],
onSelectChanged: (bool? value) {
setState(() {
selectedLignes.contains(index)
? selectedLignes.remove(index)
: selectedLignes.add(index);
});
},
);
},
);
}
}
class EditLignesDialog extends StatefulWidget {
final List&lt;int&gt; selectedLignes;
final List&lt;Map&lt;String, dynamic&gt;&gt; tableau;
final Function(List&lt;Map&lt;String, dynamic&gt;&gt;, int) saveTable;
final Map&lt;String, dynamic&gt; selectedLigneValues;
final int rapportIndex;
EditLignesDialog({
required this.selectedLignes,
required this.tableau,
required this.saveTable,
required this.selectedLigneValues,
required this.rapportIndex,
});
@override
_EditLignesDialogState createState() =&gt; _EditLignesDialogState();
}
class _EditLignesDialogState extends State&lt;EditLignesDialog&gt; {
final _formKey = GlobalKey&lt;FormState&gt;();
late TextEditingController profondeurController;
late TextEditingController inclinaisonController;
late TextEditingController numTaillantController;
late TextEditingController observationController;
bool profondeurMultipleValues = false;
bool inclinaisonMultipleValues = false;
bool numTaillantMultipleValues = false;
bool observationMultipleValues = false;
@override
void initState() {
super.initState();
profondeurController = TextEditingController(
text: widget.selectedLigneValues[&#39;Profondeur&#39;] == &#39;Valeurs multiples&#39;
? &#39;&#39;
: widget.selectedLigneValues[&#39;Profondeur&#39;]);
inclinaisonController = TextEditingController(
text: widget.selectedLigneValues[&#39;Inclinaison&#39;] == &#39;Valeurs multiples&#39;
? &#39;&#39;
: widget.selectedLigneValues[&#39;Inclinaison&#39;]);
numTaillantController = TextEditingController(
text: widget.selectedLigneValues[&#39;N&#176; taillant&#39;] == &#39;Valeurs multiples&#39;
? &#39;&#39;
: widget.selectedLigneValues[&#39;N&#176; taillant&#39;]);
observationController = TextEditingController(
text: widget.selectedLigneValues[&#39;Observation&#39;] == &#39;Valeurs multiples&#39;
? &#39;&#39;
: widget.selectedLigneValues[&#39;Observation&#39;]);
profondeurMultipleValues = hasMultipleValues(&quot;Profondeur&quot;);
inclinaisonMultipleValues = hasMultipleValues(&quot;Inclinaison&quot;);
numTaillantMultipleValues = hasMultipleValues(&quot;N&#176; taillant&quot;);
observationMultipleValues = hasMultipleValues(&quot;Observation&quot;);
}
bool hasMultipleValues(String key) {
String? firstValue;
for (int index in widget.selectedLignes) {
Map&lt;String, dynamic&gt; ligne = widget.tableau[index];
if (firstValue == null) {
firstValue = ligne[key];
} else if (ligne[key] != firstValue) {
return true;
}
}
return false;
}
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text(&#39;Editer Ligne&#39;),
content: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: profondeurController,
decoration: InputDecoration(
labelText: &#39;Profondeur&#39;,
hintText: widget.selectedLigneValues[&#39;Profondeur&#39;] ==
&#39;Valeurs multiples&#39;
? &#39;Valeurs multiples&#39;
: null,
),
validator: (value) {
if (!profondeurMultipleValues &amp;&amp; (value == null)) {
return &#39;Merci de rentrer une profondeur&#39;;
}
return null;
},
),
TextFormField(
controller: inclinaisonController,
decoration: InputDecoration(
labelText: &#39;Inclinaison&#39;,
hintText: widget.selectedLigneValues[&#39;Inclinaison&#39;] ==
&#39;Valeurs multiples&#39;
? &#39;Valeurs multiples&#39;
: null,
),
validator: (value) {
if (!inclinaisonMultipleValues &amp;&amp; (value == null)) {
return &#39;Merci d\&#39;entrer une inclinaison&#39;;
}
return null;
},
),
TextFormField(
controller: numTaillantController,
decoration: InputDecoration(
labelText: &#39;N&#176; taillant&#39;,
hintText: widget.selectedLigneValues[&#39;N&#176; taillant&#39;] ==
&#39;Valeurs multiples&#39;
? &#39;Valeurs multiples&#39;
: null,
),
validator: (value) {
if (!numTaillantMultipleValues &amp;&amp; (value == null)) {
return &#39;Merci d\&#39;entrer un num&#233;ro de taillant&#39;;
}
return null;
},
),
TextFormField(
controller: observationController,
decoration: InputDecoration(
labelText: &#39;Observation&#39;,
hintText: widget.selectedLigneValues[&#39;Observation&#39;] ==
&#39;Valeurs multiples&#39;
? &#39;Valeurs multiples&#39;
: null,
),
validator: (value) {
if (!observationMultipleValues &amp;&amp; (value == null)) {
return &#39;Merci de rentrer une observation&#39;;
}
return null;
},
),
],
),
),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(&#39;Annuler&#39;),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
bool updated = editLignes();
Navigator.pop(context,
updated); // Renvoie &#39;true&#39; si les modifications ont &#233;t&#233; effectu&#233;es
}
},
child: Text(&#39;Sauvegarder&#39;),
),
],
);
}
bool editLignes() {
for (int index in widget.selectedLignes) {
Map&lt;String, dynamic&gt; ligne = widget.tableau[index];
ligne[&#39;Profondeur&#39;] =
profondeurMultipleValues &amp;&amp; profondeurController.text.isEmpty
? ligne[&#39;Profondeur&#39;]
: profondeurController.text;
ligne[&#39;Inclinaison&#39;] =
inclinaisonMultipleValues &amp;&amp; inclinaisonController.text.isEmpty
? ligne[&#39;Inclinaison&#39;]
: inclinaisonController.text;
ligne[&#39;N&#176; taillant&#39;] =
numTaillantMultipleValues &amp;&amp; numTaillantController.text.isEmpty
? ligne[&#39;N&#176; taillant&#39;]
: numTaillantController.text;
ligne[&#39;Observation&#39;] =
observationMultipleValues &amp;&amp; observationController.text.isEmpty
? ligne[&#39;Observation&#39;]
: observationController.text;
}
widget.saveTable(widget.tableau, widget.rapportIndex);
return true; // Retourne &#39;true&#39; pour indiquer que les modifications ont &#233;t&#233; effectu&#233;es
}
}

huangapple
  • 本文由 发表于 2023年3月3日 17:50:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625514.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定