Issue
I have the following HTML:
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Item 1</td>
<td>Description of Item 1</td>
<td>
<a href="#" data-action="edit" data-item-id="1">Edit</a>
<a href="#" data-action="delete" data-item-id="1">Delete</a>
</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>Description of Item 2</td>
<td>
<a href="#" data-action="edit" data-item-id="2">Edit</a>
<a href="#" data-action="delete" data-item-id="2">Delete</a>
</td>
</tr>
</tbody>
</table>
The table rows (tr elements
) are added dynamically.
I wire up a click event to all Edit
links like this:
void wireUpTableEvents() {
var editLinks = queryAll('#order-items table tbody [data-action="edit"]');
editLinks.forEach((element) {
element.on.click.add((event){
print(element.attributes['data-item-id']);
});
});
}
As said above, the table rows (tr elements
) are added dynamically so the above code only works if I call wireUpEvents
after I execute the method which adds the rows.
Does anyone know the syntax or adding a event listener to elements using DART
‘s on.click.add()
when the elements are dynamcially added in the future?
I tried checking the DART documentation but the documentation on Event Listeners is blank.
If I would be using jQuery I could be using something similar to:
$("#order-items table")on("click", "tbody [data-action="edit"]", function(){...})
…but I want to write my sample app only using DART.
Edit
Though future
sounds great for callbacks it seemed slightly overkill for what I needed as there is no long running task in my scenario.
The closest I was able to get to attach my event listener to a static element but processing the click events of future sub-elements was this:
void wireUpTableEvents() {
var tableBody = query('#order-items table tbody');
// Attach Event Listener to the static tbody, which always exists.
tableBody.on.click.add((event) {
var clickedElement = event.srcElement;
var itemId = clickedElement.attributes['data-item-id'];
// Check if the clicked element was either one of the edit links or one of the delete links.
switch (clickedElement.attributes['data-action']) {
case 'edit':
// Replace print with calling a method to process edit request for this item.
print('processing edit click from item with id: $itemId');
break;
case 'delete':
// Replace print with calling a method to process delete request for this item.
print('processing delete click from item with id: $itemId');
break;
}
});
}
The above code can execute before any of the actual tr
elements are loaded and still works after the tr
elements are loaded at some unknown later stage.
I also found that it now covers any dynamically added row, pre-loaded ones as well as other dynamically added ones for new records etc.
Solution
It sounds like you need to use Dart’s Future object. John Evans has a recent post that gives an excellent overview. I’ll try to give a simple example:
Let’s say I have a class called htmlInDart which I call as follows:
void main() {
var htmlExample = new HtmlInDart().createStyles();
htmlExample
..then((htmlExample) => htmlExample.buildPage())
..then((htmlExample) => htmlExample.addListeners());
}
The class might look something like this:
class htmlInDart {
htmlInDart();
Future<htmlInDart> createStyles() {
final c = new Completer();
// create some styles
c.complete(this);
return c.future;
}
Future<htmlInDart> buildPage() {
final c = new Completer();
// build the page
c.complete(this);
return c.future;
}
Future<htmlInDart> addListeners() {
final c = new Completer();
// add some listeners
c.complete(this);
return c.future;
}
Hopefully this gives you some idea of how to implement it for your case.
Answered By – scribeGriff
Answer Checked By – Jay B. (FlutterFixes Admin)