Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aurelia if.bind inside repeat.for is not updating

Tags:

aurelia

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?

like image 745
esmoore68 Avatar asked Sep 20 '17 21:09

esmoore68


1 Answers

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.


like image 153
adiga Avatar answered Oct 10 '22 20:10

adiga