Permalink
Browse files

feature: MaterialRepeat / ObservableList got callback for fast rendering

  • Loading branch information...
MikeMitterer committed Mar 8, 2017
1 parent 297269c commit 46d70f6f63ff06c2aed72539f25efe887e2eb49c
View
@@ -19,8 +19,9 @@
library mdlobservable;
import 'dart:collection';
import "dart:async";
import 'dart:collection';
import 'dart:html' as dom;
import 'package:logging/logging.dart';
import "package:mdl/mdlcore.dart";
@@ -181,6 +181,7 @@ void createSampleList() {
samples.add(new Sample("observe", Type.Directive, hasOwnDartMain: true, hasOwnDemoHtml: true));
samples.add(new Sample("repeat", Type.Directive, hasOwnDartMain: true, hasOwnDemoHtml: true));
samples.add(new Sample("repeat_data-table", Type.Directive, hasOwnDartMain: true, hasOwnDemoHtml: true));
samples.add(new Sample("repeat_callback", Type.Directive, hasOwnDartMain: true, hasOwnDemoHtml: true));
// SPA Samples
samples.add(new Sample("content", Type.SPA, hasOwnDartMain: true, hasOwnDemoHtml: true));
@@ -23,26 +23,79 @@ enum ListChangeType {
ADD, INSERT, UPDATE, REMOVE, CLEAR
}
typedef bool UpdateItem<T>(final dom.HtmlElement element, final T item);
/// Propagated if List changes
class ListChangedEvent<T> {
/// [changetype] shows what changed
final ListChangeType changetype;
/// [item] is set on ADD, REMOVE and update
final Object item;
final T item;
/// [prevItem] is set on UPDATE and defines the old Entry
/// It is also set on INSERT. It defines the previous items a the given index
final Object prevItem;
final T prevItem;
ListChangedEvent(this.changetype,{ final Object this.item, final this.prevItem });
ListChangedEvent(this.changetype,{ final T this.item, final this.prevItem });
}
/**
* List that sends [ListChangeEvents] to the listener if this list changes
* Supported methods:
* Add, insert, update ([]), remove, clear, removeAll
*/
/// List that sends [ListChangeEvents] to the listener if this list changes
/// Supported methods:
/// Add, insert, update ([]), remove, clear, removeAll
///
/// @MdlComponentModel
/// class MyComponent extends MdlTemplateComponent {
///
/// final ObservableList<RecordsPerDay> records = new ObservableList<RecordsPerDay>(
/// updateCallback: _updateListItem);
///
/// void _init() {
///
/// render().then((_) {
/// _bindStoreActions();
/// });
/// }
///
/// void _bindStoreActions() {
/// if(_store == null) { return;}
///
/// _store.onChange.listen((final DataStoreChangedEvent event) {
/// _updateView();
/// });
/// }
///
/// void _updateView() {
///
/// if(records.length != _store.records.length) {
/// records.clear();
/// records.addAll(_store.records);
///
/// } else {
/// final List<RecordsPerDay> _storeRecords = _store.records;
/// for (int index = 0; index < _storeRecords.length; index++) {
///
/// // Triggers _updateListItem!!! in MaterialRepeat
/// records[index] = _storeRecords[index];
/// }
/// }
/// }
///
/// static bool _updateListItem(final dom.HtmlElement element, final RecordsPerDay item, final RecordsPerDay prevItem) {
/// if(element == null) {
/// return false;
/// }
/// final dom.SpanElement date = element.querySelector(".date");
/// final dom.SpanElement records = element.querySelector(".records");
/// date.text = item.date.toString();
/// records.text = item.records.toString();
/// return true;
/// }
///
/// @override
/// final String template = "...";
/// }
///
@MdlComponentModel
class ObservableList<T> extends ListBase<T> {
//final Logger _logger = new Logger('mdlobservable.ObservableList');
@@ -52,10 +105,18 @@ class ObservableList<T> extends ListBase<T> {
StreamController<ListChangedEvent<T>> _onChange;
final UpdateItem _updateCallback;
/// If [updateCallback] is given it will be called from [MaterialRepeat]
/// if the list updates
ObservableList({final UpdateItem updateCallback: _defaultUpdateCallback })
: _updateCallback = updateCallback;
/// Propagated Event-Listener
Stream<ListChangedEvent<T>> get onChange {
if(_onChange == null) {
_onChange = new StreamController<ListChangedEvent<T>>.broadcast(onCancel: () => _onChange = null);
_onChange = new StreamController<ListChangedEvent<T>>.broadcast(
onCancel: () => _onChange = null);
}
return _onChange.stream;
}
@@ -66,6 +127,7 @@ class ObservableList<T> extends ListBase<T> {
_innerList.length = length;
}
/// Updates the internal List.
void operator []=(int index, T value) {
_fire(new ListChangedEvent<T>(ListChangeType.UPDATE,
item: value,
@@ -134,7 +196,7 @@ class ObservableList<T> extends ListBase<T> {
@override
bool remove(final Object element) {
_fire(new ListChangedEvent<T>(ListChangeType.REMOVE,item: element ));
_fire(new ListChangedEvent<T>(ListChangeType.REMOVE,item: element as T ));
return _innerList.remove(element);
}
@@ -194,6 +256,10 @@ class ObservableList<T> extends ListBase<T> {
}
}
/// Called by MaterialRepeat do make fast updates
bool update(final dom.HtmlElement element, final T item)
=> _updateCallback(element,item);
//- private -----------------------------------------------------------------------------------
void _fire(final ListChangedEvent<T> event) {
@@ -212,4 +278,11 @@ class ObservableList<T> extends ListBase<T> {
void _clearFilter() {
_filterBackup.clear();
}
/// Default Callback for updating the UI
///
/// It returns false which indicates that MaterialRepeater should call it's own
/// update routines
static bool _defaultUpdateCallback<T>(final dom.HtmlElement element, final T item) => false;
}
Oops, something went wrong.

0 comments on commit 46d70f6

Please sign in to comment.