Closed bugged84 closed 5 years ago
It's possible to do what you describe, unfortunately not with the DataGrid element at the moment. The underlying library, react-data-grid, seems to have an issue with rendering change on a row when it's not the selected row.
What you can do is create your own grid, (you can use Cell elements, see example at http://www.dotnetify.net/elements/structure/cell).
You don't need to the row to be view model objects, just use the CRUD APIs with PushUpdates
to update a row. When the view model inherits from MulticastVM, the update will be sent to all connections.
Ah, I see. I'll try that approach and post back here with the result. Great library by the way. I like the new elements addition.
BTW, the suggested CRUD APIs worked for this scenario.
Consider the case:
RowData contains an Observable
property Status
, which is a Subject
that receives notifications from a source observable that is outside of my app. How/Where should I use the CRUD APIs: this.UpdateList(propertyName, item)
in order to push the update to each row in the view?
Thanks.
public class RowData
{
public string Id { get; set; }
public IObservable<string> Status { get; set; }
}
public class RowService
{
public IObservable<RowData> Rows {get;}
}
View models
public class RowList : BaseVM
{
public string Records_itemKey => nameof(RowData.Id);
public ReactiveProperty<Row[]> Rows = new ReactiveProperty<Row[]>();
public RowList(RecordService recordService)
{
Rows.SubscribeTo(rowService.Rows.Select(value =>
{
var records= new Queue<Row>(Get<Row[]>("Rows")?.Reverse() ?? new Row[] { });
records.Enqueue(new Row(value));
return records.ToArray();
})).SubscribedBy(AddInternalProperty<bool>("Update"), _ =>
{
PushUpdates();
return true;
});
}
}
public class Row : BaseVM
{
RowData _record;
public ReactiveProperty<string> Status= new ReactiveProperty<string>();
public Row(RowData record)
{
_record = record;
Status.SubscribeTo(record.Status)
.SubscribedBy(AddInternalProperty<bool>("Update"), _ =>
{
PushUpdates();
return true;
});
}
}
Views
export default class RowList extends React.Component<Props, State> {
dispatch: (state: any) => dotnetifyVM;
vm: any;
constructor(props) {
...
this.vm = dotnetify.react.connect("RowList", this);
...
}
render() {
...
return (
...
<RowListTable data={Records} />
...
);
}
}
export default class RowListTable extends React.Component<Props, any> {
render() {
const records = this.props.data;
return (
<Table>
...
<TableBody>
{records.map(item => (
<TableRow key={item.Id}>
<TableCell>{item.Status}</TableCell>
...
</TableRow>
))}
</TableBody>
</Table >
);
}
}
There's no need for Row
to inherit from BaseVM
; instead, subscribe to Status
from RowList
:
public class RowList : BaseVM
{
public string Rows_itemKey => nameof(RowData.Id);
public RowList(RecordService recordService)
{
AddProperty<Row[]>("Rows").SubscribeTo(rowService.Rows.Select(value =>
{
var records = new Queue<Row>(Get<Row[]>("Rows")?.Reverse() ?? new Row[] { });
records.Enqueue(new Row(value));
value.Status.Subscribe(newStatus =>
{
this.UpdateList("Rows", new Row(value, newStatus));
PushUpdates();
});
return records.ToArray();
})).SubscribedBy(AddInternalProperty<bool>("Update"), _ =>
{
PushUpdates();
return true;
});
}
}
Thanks it works!
Consider the customer form example from the docs.
What if I want the row items to be updated in real-time for all users if any user updates one of the row items? Is there a way to make the row items a view model class instead of a POCO class such that changes are pushed to all clients?