I have a strange case in an Aurelia template of elements with if.bind inside a repeat.for not being shown/hidden when their underlying property is changed. With the following code, the edit fields should be shown and the edit button should be hidden as soon as the edit button is clicked. Subsequently, both the save and undo buttons should hide the edit fields and show the edit buttons again.
MyList.ts:
import { computedFrom } from "aurelia-binding";
export class MyList
{
items: any[] = [{
"firstName": "Joe",
"lastName" : "Blow",
"id": 1
},
{
"firstName": "Jane",
"lastName" : "Doe",
"id": 2
}
]
editingItem: any = null
isEditing: boolean;
edit(item){
this.editingItem = item;
this.isEditing = true;
}
editFirst(item){
this.editingItem = this.items[0];
this.isEditing = true;
}
undo(){
// undo logic here
this.editingItem = null;
this.isEditing = false;
}
save(){
// Save logic here
this.editingItem = null;
this.isEditing = false;
}
}
MyList.html:
<template>
<table>
<tbody>
<tr repeat.for="item of items">
<td if.bind="!isEditing">
<button click.delegate="edit(item)">Edit</button>
</td>
<td>${item.firstName}</td>
<td>${item.lastName}</td>
<td if.bind="isEditing && editingItem.id == item.id">
<button click.delegate="save()">Save</button>
<button click.delegate="undo()">Undo</button>
<input value.bind="editingItem.firstName" />
<input value.bind="editingItem.lastName" />
</td>
</tr>
</tbody>
</table>
</template>
Clicking the edit button does nothing. Interestingly, if I add
${isEditing}
Anywhere in the template outside the repeat.for, the code works as expected. It's as if the rendering engine doesn't know to re-render elements inside the repeat loop.
Is this a bug? Or am I doing something silly?
This is weird. I created a gist from your code and as you said it wasn't working. No errors in the console either.
But when I initialized isEditing
it started working
isEditing: boolean = false;
Updated gist
From @Balázs in the comments: By not initializing the isEditing
, that property virtually does not exist -- it can be used for autocompletion/IntelliSense, but it is not actually present on the object. You can verify that by replacing the console.log
call in the edit method with console.log(this.editing);
, you will see that it is undefined
. By it being undefined
, Aurelia cannot subscribe
to it (because it is as though it wasn't even there - no getter/setter exists), and therefore has no way of knowing when, if ever, it comes to life. However, that even explicitly setting it to undefined
is different from this, because that does actually create the property, whose value happens to be set to undefined
.
Also note:
Since you are assigning editingItem
directly with item
here:
edit(item){
this.editingItem = item;
this.isEditing = true;
}
Whatever you change in editingItem
will affect item
as well. So even if you undo
, the change will persist to item
. So you should do a clone
before assigning to editingItem
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With