1
votes

I have the following fragment in a web component:

<div id="mycodes">                     
<template iterate='code in codeList'>
   {{code}}
</template>  
</div> 

And in a Dart file, codeList is populated when the user clicks on a button:

void onMyButtonClick(Event  event) {
  HttpRequest.getString('http://getData').then((response) {
  mylist = json.parse(response);
  for(var code  in mylist){
    codeList.add(code['c']);
  }
}

The problem is that I don't see data on first click. I need to click the button twice to see data.

But if I fill codeList manually (not from network data) as shown below, then I see the data on first click:

void onMyButtonClick(Event  event) {

    codeList.add("data 1");
    codeList.add("data 2");
  }
}

I need the template to iterate after the network data is available. It appears that event loop has already done its job of painting a page before the network data becomes available through future object. Is there a way to refresh the page after model is updated in dart?

2
Can you show us the declaration of codeList?ianmjones
are you sure that first request to 'http://getData' returns what you expect?Zdeslav Vojkovic

2 Answers

2
votes

The reason your codeList currently populates if you add it with the on-click event is because the current web_ui has 'watchers' which automatically are called when an event happens. You then populate the list synchronously. However one of the downfalls of watchers is exactly your use case, when the data is updated asynchronously then the watchers don't reflect changes in time.

As a result the watchers are being phased out and replaced with observables. Observables allow us to flag a variable to be watched for reassignment and when that happens it will cause the view to change. For example:

@observable int x = 0;
// ...
x = 1;

When the x = 1 is called later in the code it automatically triggers the views to update. This leaves us with one problem however. When you are adding to a list, you are not reassigning the value itself. As such, observables also offer a function to convert a list to an observable list (this also works for maps).

For instance if you changed your declaration of codeList to something like the following, then when you add to the list later it will update accordingly.

var codeList = toObservable([]); // Assuming it starts with an empty list
// or
var codeList = toObservable(_startCodeList); // if you already have a list

Also see the Dart Tutorial: Target 7 for more information on using @observable and toObservable. For more in-depth information, check out the article on Observables and Data Binding

0
votes

You need to mark the fields you want WebUi to monitor with the @observable annotation. Otherwise you only get the initial value not any subsequent updates.

You can do this either directly on the object declaration or you can make the entire class as observable and all its fields will then be observed.

For an example see http://www.dartlang.org/docs/tutorials/custom-elements/#using-two-way-data-binding