jai pundir
jai pundir

Reputation: 49

How to bind data from Web API in Aurelia JS?

I have json data which I get from call Web API. Code as below

export class App {

constructor() {

    this.empRecords = null;
    this.fetchEmployees();
}

fetchEmployees() {
    httpClient.fetch('http://localhost:61517/odata/emps')
        .then(response => response.json())
        .then(data => {
            this.empRecords = data;
        });
}

}

When i bind this json data in html table. html code as below :

 <table border="1">
    <thead>
        <tr>
            <td><b>First Name</b></td>
            <td><b>Last Name</b></td>
            <td><b>Age</b></td>
            <td><b>Gender</b></td>
            <td><b>Department</b></td>
        </tr>
    </thead>
    <tbody>
        <tr repeat.for="emp of empRecords">

            <td>${emp.fname}</td>
            <td>${emp.lname}</td>
            <td>${emp.age}</td>
            <td>${emp.gender}</td>
            <td>${emp.department}</td>
        </tr>
    </tbody>
</table>

it is unable to bind data in html table. It showing following error :

Uncaught Error: Value for 'empRecords' is non-repeatable

How can i bind the data in html table in aurelia js.

Upvotes: 3

Views: 517

Answers (3)

Bal&#225;zs
Bal&#225;zs

Reputation: 2929

The problem is that before the response arrives, the array is null, which, as the error says, not repeatable. You either guard the repeat.for element with an if or set the empRecords property to an empty array rather than null. You can even use both.

Approach 1:

<tbody if.bind="empRecords && empRecords.length">
  <tr repeat.for="emp of empRecords">
    <td>${emp.fname}</td>
    <td>${emp.lname}</td>
    <td>${emp.age}</td>
    <td>${emp.gender}</td>
    <td>${emp.department}</td>
  </tr>
</tbody>
<tbody if.bind="!empRecords || !empRecords.length">
  <tr>
    <td colspan="5">No data</td>
  </tr>
</tbody>

Approach 2:

export class App {

  constructor() {
    this.empRecords = [];
    this.fetchEmployees();
  }
}

By setting the empRecords to [] rather than null, it becomes repeatable just it will be empty.

Also, based on your feedback, your response structure contains the values within an embedded property. Modify the fetchData method like this:

fetchEmployees() {
  var self = this;

  httpClient.fetch('http://localhost:61517/odata/emps')
    .then(response => response.json())
    .then(data => {
      self.empRecords = data.value;
    });
}

Upvotes: 3

Jesse
Jesse

Reputation: 3622

Your JSON is not an array, but contains a value that contains the array you want to bind to. Something like this should do the trick:

httpClient.fetch('http://localhost:61517/odata/emps')
    .then(response => response.json())
    .then(data => {
        this.empRecords = data.value;
    });

Edit: as suggested in the other answer, you should also initialize your empRecords by setting

this.empRecords = []

in the constructor.

JSON returned by httprequest:

{
  "odata.metadata":"localhost:61517/odata/$metadata#emps",
  "va‌​lue": [
    {
      "id":1004,
      "fn‌​ame":"jai",
      "lname":"‌​pundir",
      "age":23,
      "ge‌​nder":"Male",
      "depart‌​ment":"IT"
    },
    {
      "id":10‌​05,
      "fname":"ram",
      "ln‌​ame":"singh",
      "age":2‌​4,
      "gender":"male",
      "d‌​epartment":"HR"
    }
  ]
}

Upvotes: 0

flx
flx

Reputation: 1578

this is not referencing class App() when you call it inside

.then(data => {
    this.empRecords = data;
});

I'm not sure but try using:

export class App {

    constructor() {
        this.empRecords = null;
        this.fetchEmployees();
    }

    fetchEmployees() {
        var self = this;

        httpClient.fetch('http://localhost:61517/odata/emps')
            .then(response => response.json())
            .then(data => {
                self.empRecords = data;
            });
    }

Upvotes: -1

Related Questions