The goal is to load data and display it in a children dropdown as shown in the image:
the expected result is that when I click on a reference choice whose children are not present, the app should load them and display them.
This is the prompt I inserted into claude/chatgpt but I have not been able to get it to work:
When a user clicks on the arrow icon and it does not have any children, load the children
code1:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'right_click_menu.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Right Click Menu Example'),
),
body: Builder(
builder: (context) => Listener(
onPointerDown: (PointerDownEvent event) {
final List<Map<String, dynamic>> buttons = [
{'sys_id': '1', 'sys_name': 'Option 1', 'sys_type': 'bool'},
{'sys_id': '2', 'sys_name': 'Option 2', 'sys_type': 'num'},
{'sys_id': '3', 'sys_name': 'Submenu', 'sys_type': 'reference'},
{'sys_id': '4', 'sys_name': 'Sub-option 1', 'sys_type': 'reference'},
{'sys_id': '5', 'sys_name': 'Sub-option 2', 'sys_type': 'text'},
];
final Map<String, List<String>> parentChildRelationships = {
'3': ['4', '5'],
};
RightClickMenu.display_right_click_menu(
e: event,
context: context,
buttons: buttons,
parentChildRelationships: parentChildRelationships,
load_children: load_children,
);
},
child: Center(
child: Text('Right-click anywhere in this area!'),
),
),
),
),
);
}
Future<void> load_children(String id)async{
// add dummy children to buttons and link them in parentChildRelationships
}
}
code2:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class RightClickMenu {
static Future<void> display_right_click_menu({
required PointerDownEvent e,
required BuildContext context,
required List<Map<String, dynamic>> buttons,
required Map<String, List<String>> parentChildRelationships,
required Function(String) load_children,
}) async {
if (e.kind != PointerDeviceKind.mouse || e.buttons != kSecondaryMouseButton || buttons.isEmpty) {
return; //
}
final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
final position = RelativeRect.fromLTRB(
e.position.dx,
e.position.dy,
overlay.size.width - e.position.dx,
overlay.size.height - e.position.dy,
);
await showMenu(
context: context,
position: position,
items: _buildMenuItems(
null,
buttons,
parentChildRelationships,
load_children,
context
),
);
}
// Helper method to find a button by its ID
static Map<String, dynamic>? _findButtonById(String id, List<Map<String, dynamic>> allButtons) {
return allButtons.firstWhere(
(button) => button['sys_id'] == id,
orElse: () => {},
);
}
static List<PopupMenuEntry> _buildMenuItems(
String? parentId,
List<Map<String, dynamic>> buttons,
Map<String, List<String>> parentChildRelationships,
Function(String) trigger_menu_script,
BuildContext context
) {
List<PopupMenuEntry> menuItems = [];
List<Map<String, dynamic>> filteredItems = [];
if (parentId == null) {
// Top-level menu: show only buttons that are NOT children of another button
filteredItems = buttons.where((button) {
String buttonId = button['sys_id'] ?? '';
return !parentChildRelationships.values.any((children) => children.contains(buttonId));
}).toList();
} else {
// Get child buttons of the specified parent
List<String> childIds = parentChildRelationships[parentId] ?? [];
filteredItems = childIds
.map((id) => _findButtonById(id, buttons))
.where((button) => button != null)
.toList()
.cast<Map<String, dynamic>>();
}
for (var i = 0; i < filteredItems.length; i++) {
var item = filteredItems[i];
String sysId = item['sys_id'] ?? '';
String name = item['sys_name'] ?? 'Unnamed';
// Check if this item has children
bool hasChildren = parentChildRelationships.containsKey(sysId);
// Offset calculations for submenu positioning
double x_offset = i == 0 ? 125 : 183;
if (hasChildren) {
menuItems.add(
PopupMenuItem(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(name),
PopupMenuButton(
offset: Offset(x_offset, 0),
child: const Icon(Icons.arrow_right),
itemBuilder: (_) => _buildMenuItems(
sysId,
buttons,
parentChildRelationships,
trigger_menu_script,
context
),
),
],
),
),
);
} else {
menuItems.add(
PopupMenuItem(
value: sysId,
child: Text(name),
onTap: () {
trigger_menu_script(sysId);
},
),
);
}
}
return menuItems;
}
}
the image example is taken from the code below. as you can tell it appears to load the data but its never displayed.
code1:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'right_click_menu.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// Store menu data in state
late List<Map<String, dynamic>> buttons;
late Map<String, List<String>> parentChildRelationships;
@override
void initState() {
super.initState();
// Initialize menu data
buttons = [
{'sys_id': '1', 'sys_name': 'Option 1', 'sys_type': 'bool'},
{'sys_id': '2', 'sys_name': 'Option 2', 'sys_type': 'num'},
{'sys_id': '3', 'sys_name': 'Submenu', 'sys_type': 'reference'},
{'sys_id': '4', 'sys_name': 'Sub-option 1', 'sys_type': 'reference'},
{'sys_id': '5', 'sys_name': 'Sub-option 2', 'sys_type': 'text'},
];
parentChildRelationships = {
'3': ['4', '5'],
};
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Right Click Menu Example'),
),
body: Builder(
builder: (context) => Listener(
onPointerDown: (PointerDownEvent event) {
RightClickMenu.display_right_click_menu(
e: event,
context: context,
buttons: buttons,
parentChildRelationships: parentChildRelationships,
load_children: load_children,
);
},
child: Center(
child: Text('Right-click anywhere in this area!'),
),
),
),
),
);
}
Future<void> load_children(String id) async {
// Simulate loading delay
await Future.delayed(Duration(seconds: 1));
// Update state with new children
setState(() {
// Check if the item already has children
if (!parentChildRelationships.containsKey(id)) {
// Generate new children
String childId1 = 'child_${id}_1';
String childId2 = 'child_${id}_2';
// Add new children to buttons list
buttons.add({
'sys_id': childId1,
'sys_name': 'Dynamic Child 1 of $id',
'sys_type': 'text'
});
buttons.add({
'sys_id': childId2,
'sys_name': 'Dynamic Child 2 of $id',
'sys_type': 'reference' // This could potentially have children too
});
// Update parent-child relationships
parentChildRelationships[id] = [childId1, childId2];
}
});
}
}
code2:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class RightClickMenu {
static Future<void> display_right_click_menu({
required PointerDownEvent e,
required BuildContext context,
required List<Map<String, dynamic>> buttons,
required Map<String, List<String>> parentChildRelationships,
required Function(String) load_children,
}) async {
if (e.kind != PointerDeviceKind.mouse || e.buttons != kSecondaryMouseButton || buttons.isEmpty) {
return; //
}
final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
final position = RelativeRect.fromLTRB(
e.position.dx,
e.position.dy,
overlay.size.width - e.position.dx,
overlay.size.height - e.position.dy,
);
await showMenu(
context: context,
position: position,
items: _buildMenuItems(null, buttons, parentChildRelationships, load_children, context),
);
}
// Helper method to find a button by its ID
static Map<String, dynamic>? _findButtonById(String id, List<Map<String, dynamic>> allButtons) {
return allButtons.firstWhere(
(button) => button['sys_id'] == id,
orElse: () => {},
);
}
static List<PopupMenuEntry> _buildMenuItems(String? parentId, List<Map<String, dynamic>> buttons, Map<String, List<String>> parentChildRelationships, Function(String) load_children, BuildContext context) {
List<PopupMenuEntry> menuItems = [];
List<Map<String, dynamic>> filteredItems = [];
if (parentId == null) {
// Top-level menu: show only buttons that are NOT children of another button
filteredItems = buttons.where((button) {
String buttonId = button['sys_id'] ?? '';
return !parentChildRelationships.values.any((children) => children.contains(buttonId));
}).toList();
} else {
// Get child buttons of the specified parent
List<String> childIds = parentChildRelationships[parentId] ?? [];
filteredItems = childIds.map((id) => _findButtonById(id, buttons)).where((button) => button != null).toList().cast<Map<String, dynamic>>();
}
for (var i = 0; i < filteredItems.length; i++) {
var item = filteredItems[i];
String sysId = item['sys_id'] ?? '';
String name = item['sys_name'] ?? 'Unnamed';
// Check if this item has children or is a "reference" type that might have children
bool hasChildren = parentChildRelationships.containsKey(sysId);
bool isReferenceType = item['sys_type'] == 'reference';
// Offset calculations for submenu positioning
double x_offset = i == 0 ? 125 : 183;
if (hasChildren || isReferenceType) {
menuItems.add(
PopupMenuItem(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(name),
PopupMenuButton(
offset: Offset(x_offset, 0),
child: const Icon(Icons.arrow_right),
itemBuilder: (BuildContext context) {
// If this item doesn't have children but is a reference type,
// trigger the load_children function first
if (!hasChildren && isReferenceType) {
// Using Future.delayed to ensure the menu is built after the children are loaded
Future.delayed(Duration.zero, () => load_children(sysId));
// Return a loading indicator while children are being loaded
return [
PopupMenuItem(
enabled: false,
child: Center(
child: SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
),
),
];
}
// Otherwise, build the submenu as normal
return _buildMenuItems(sysId, buttons, parentChildRelationships, load_children, context);
},
),
],
),
),
);
} else {
menuItems.add(
PopupMenuItem(
value: sysId,
child: Text(name),
onTap: () {
load_children(sysId);
},
),
);
}
}
return menuItems;
}
}
at this point im not sure what to do. the stack overflows I found dont dynamically load data in a manner that I am looking for like these ones:
How can I make a multi level dependable dropdown List in Flutter?
How to build dependent dropdown menus in Flutter?
as you can see they mention 1/3 of the solution I want. they have dependent dropdown logic, but its not even close to what I am looking for.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744905272a4600217.html
评论列表(0条)