data binding in datagrid
can someone please help me why data is not being updated in DataGrid below is the simple code. Log is showing that data is updated in arraylist but same is reflecting in datagrid
MXML-------
<j:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:j="library://ns.apache.org/royale/jewel" xmlns:js="library://ns.apache.org/royale/basic"
initComplete="init()" style="background:transparent; border: none;" >
<j:beads>
<js:ContainerDataBinding/>
</j:beads>
<fx:Script>
<![CDATA[
import views.actionitemviews.websocket.SocketService;
import org.apache.royale.collections.ArrayList;
[Bindable]
private var _stockList:ArrayList = new ArrayList();
private var _socketService:SocketService;
private function init():void {
_socketService = new SocketService();
_socketService.addCAllBackFunction(onSocketData);
_socketService.connectWebSocket(SocketService.SUBSCRIBE_STOCK);
}
private function onSocketData(data:Object):void {
if (data.type == "stock_update") {
//console.log("📈 Stock update:", data.payload);
updateFromJSON(data.payload); // we’ll structure this properly below
} else {
console.log("📩 Other data received:", data);
}
}
public function updateFromJSON(json:Array):void {
var updatedSymbols:Object = {};
for each (var obj:Object in json) {
updatedSymbols[obj.symbol] = obj;
// Check if stock already exists
var found:Boolean = false;
for (var i:int = 0; i < _stockList.length; i++) {
var existing:StockModel = _stockList.getItemAt(i) as StockModel;
if (existing.symbol === obj.symbol) {
existing.price = obj.price;
existing.timestamp = obj.timestamp;
// console.log(obj.symbol, obj.price, obj.timestamp)
found = true;
break;
}
}
// If not found, add new
if (!found) {
_stockList.addItem(new StockModel(obj.symbol, obj.price, obj.timestamp));
}
}
console.log('_stockList'+_stockList.getItemAt(0).price)
}
public function disposeMe():void {
var obj:Object = {"type": "unsubscribe_stock"}
_socketService.sendToSocket(obj);
console.log('unsubscribe_stock')
_socketService.disconnectWebSocket();
}
]]>
</fx:Script>
<j:DataGrid id="dg1" dataProvider="{_stockList}" width="100%">
<j:columns>
<j:DataGridColumn dataField="symbol" label="Symbol"/>
<j:DataGridColumn dataField="price" label="Price"/>
<j:DataGridColumn dataField="timestamp" label="Time"/>
</j:columns>
</j:DataGrid>
</j:View>
SocketModel.as
package views.actionitemviews.stockSocket {
[Bindable]
public class StockModel {
public var symbol:String;
public var price:Number;
public var timestamp:String;
public function StockModel(symbol:String, price:Number, timestamp:String = "") {
this.symbol = symbol;
this.price = price;
this.timestamp = timestamp;
}
}
}
The binding only works if you change the entire ArrayList. In your case, you're adding items to _stockList, but for the binding to work, you must set _stockList = _dataList. _dataList would be an ArrayList or temporary Array initialized with _stockList.
@mjesteve your suggestion works but it seems as good as declaring a new array on each update which makes binding nature redundant. Also, binding or without binding, displaying 500+ data in Datagrid/ List using ArrayList is terribly slow when data keeps changes/ updating on each 500ms to 1000ms. I can hope things will improve in near future.
My custom UI performance is far batter then native DataGrid/ List component https://sanjeev-rajput.github.io/Apache-royale-demo/index.html - (Live Stock)
In my case, I'm using List/VirtualList components. When pagination is enabled, virtualization becomes less critical, but since the number of records per page is user-configurable, it's generally safer to keep it in place.
I was also surprised the first time I noticed this behavior. But if you think about it, when we bind an object, what we're actually binding is the reference to that object — not the internal changes to its individual sub-properties or nested elements.
I recall reading something on the mailing lists regarding this: to properly track changes in nested elements, we need to manually set up listeners for each item.
In my current implementation, I’m using an ArrayListView to handle pagination, and when I execute:
getAsourceAll.list.setItemAt(imodel.selectedItem, nreg);
getAsource.setItemAt(imodel.selectedItem, nreginpage);
the visual updates on both lists are reflected correctly.
You can find examples of this approach in my test project, specifically in the pagination section: https://github.com/mjesteve/royale-examples-community
I'm very interested in your test application. I've been exploring the possibility of combining Jewel and Spectrum components for a while now, and I see you’ve successfully integrated both. Would you be willing to share your test project or provide an example?
Sorry, I just noticed that your demo repository is public. I'll take a look at it as soon as I have a free moment. :P