Permalink
Browse files

feature: MaterialContent is now ScopeAware - works nice with Material…

…Controller
  • Loading branch information...
MikeMitterer committed Nov 9, 2017
1 parent b34d9c0 commit b490746b383922c553f6bdc8f8a679a37bb8a533
@@ -14,6 +14,8 @@
// limitations under the License.
//
@import "../theme/theme";
// ========= Footer =========
$footer-bg-color: ($palette-grey-800) !default;
@@ -21,7 +21,7 @@ part of mdlapplication;
abstract class MaterialController {
/**
* {injector} will be set after {ViewFactory} receives the {onLoadEnd} Event
* [injector] will be set after {ViewFactory} receives the {onLoadEnd} Event
*
* Part in ViewFactory:
* main.render(content).then( (_) {
@@ -31,7 +31,9 @@ abstract class MaterialController {
*/
di.Injector injector;
/// {loaded} is called after {ViewFactory} received the {onLoadEnd} Event
/// [loaded] is called after [ViewFactory] received the onLoadEnd-Event
///
/// At this point the Template is already rendered
void loaded(final Route route);
/// Called before the next controller is loaded
@@ -39,20 +39,88 @@ MdlConfig materialContentConfig() => new MdlWidgetConfig<MaterialContent>(
/// registration-Helper
void registerMaterialContent() => componentFactory().register(materialContentConfig());
class MaterialContent extends MdlComponent {
/// MaterialContent is [ScopeAware] - this means that it can be found by child-MaterialComponent
/// looking for Data (like [MaterialRepeat]
///
/// Unlike other [ScopeAware] components MaterialContent redirects its [Scope] to
/// [MaterialApplication]
///
/// This means if you have a smaller Application you can implement your observable properties
/// in your Application
///
/// @Model
/// class Application extends MaterialApplication {
/// final ObservableProperty<String> time = new ObservableProperty<String>("",interval: new Duration(seconds: 1));
///
/// Application() {
/// time.observes(() => _getTime());
/// }
///
/// String _getTime() {
/// final DateTime now = new DateTime.now();
/// return "${now.hour.toString().padLeft(2,"0")}:${now.minute.toString().padLeft(2,"0")}:${now.second.toString().padLeft(2,"0")}";
/// }
/// }
///
/// If you use routes and [MaterialController] implement the [ScopeAware] and tag your
/// Controller with [Model]
///
/// @mdl.Model
/// class ObservableController extends mdl.MaterialController implements ScopeAware {
/// final ObservableProperty<String> time
/// = new ObservableProperty<String>("",interval: new Duration(seconds: 1));
///
/// @override
/// void loaded(final Route route) {
/// time.observes(() => _getTime());
/// }
///
/// @override
/// mdl.Scope get scope => new mdl.Scope(this);
///
/// String _getTime() {
/// final DateTime now = new DateTime.now();
/// return "${now.hour.toString().padLeft(2,"0")}:${now.minute.toString().padLeft(2,"0")}:${now.second.toString().padLeft(2,"0")}";
/// }
/// }
class MaterialContent extends MdlComponent implements ScopeAware {
final Logger _logger = new Logger('mdlapplication.MaterialContent');
static const _MaterialContentCssClasses _cssClasses = const _MaterialContentCssClasses();
final DomRenderer _renderer;
Scope scope;
MaterialContent.fromElement(final dom.HtmlElement element,final di.Injector injector)
: _renderer = injector.getInstance(DomRenderer), super(element,injector) {
}
@override
void attached() {
scope = new Scope(mdlRootContext());
_init();
}
static MaterialContent widget(final dom.HtmlElement element) => mdlComponent(element,MaterialContent) as MaterialContent;
/// Sets the scope back to it's original value
///
/// We have one MaterialContent with multiple [MaterialController]s but it the
/// [MaterialController] is not [ScopeAware] we have to switch back to [Application]-scope
///
/// class ViewFactory {
/// ...
/// if(controller is ScopeAware) {
/// main.scope = (controller as ScopeAware).scope;
/// }
/// else {
/// main.resetScope();
/// }
/// ...
/// }
///
void resetScope() => scope = new Scope(mdlRootContext());
// Central Element - by default this is where mdl-content was found (element)
// html.Element get hub => inputElement;
@@ -68,7 +68,7 @@ class Scope {
Object _rootContext;
/// [_parentScope] can be null if there is no parent
Scope(this._context,this._parentScope);
Scope(this._context,[ this._parentScope ]);
Object get context => _context;
void set context(final Object cntxt) {
@@ -66,7 +66,7 @@ class ViewFactory {
final dom.Element contentElement = dom.querySelector(selector);
if(contentElement == null) {
_logger.severe('Please add <div id="$selector" class="mdl-content mdl-js-content">Loading...</div> to your index.html');
_logger.severe('Please add <div id="$selector" class="mdl-content">Loading...</div> to your index.html');
return;
}
@@ -84,6 +84,16 @@ class ViewFactory {
final String content = _sanitizeResponseText(request.responseText);
final MaterialContent main = MaterialContent.widget(contentElement);
if(controller is ScopeAware) {
// If you have observable-Properties in your Controller it must be
// marked as [@mdl.Model]
// TODO: Check controller if it has a Annotation
main.scope = (controller as ScopeAware).scope;
}
else {
main.resetScope();
}
main.render(content).then( (_) {
controller.injector = main.injector;
@@ -59,7 +59,7 @@ abstract class RefreshableComponent {
/**
* For Components like [_MaterialDialogComponent] where it's necessary to
* change the ParentScope on runtime. For example if [MaterialDialog] pops up
* change the ParentScope at runtime. For example if [MaterialDialog] pops up
* the Parent-Scope is set to the new Dialog
*/
abstract class HasDynamicParentScope {
@@ -30,7 +30,7 @@ class ListChangedEvent<T> {
/// [changetype] shows what changed
final ListChangeType changetype;
/// [item] is set on ADD, REMOVE and update
/// [item] is set on ADD, REMOVE and UPDATE
final T item;
/// [prevItem] is set on UPDATE and defines the old Entry
@@ -101,7 +101,7 @@ class ListChangedEvent<T> {
///
@Directive
class ObservableList<T> extends ListBase<T> {
//final Logger _logger = new Logger('mdlobservable.ObservableList');
final Logger _logger = new Logger('mdlobservable.ObservableList');
final List<T> _innerList = new List();
final List<T> _filterBackup = new List();
@@ -285,6 +285,42 @@ class ObservableList<T> extends ListBase<T> {
bool update(final dom.HtmlElement element, final T item)
=> _updateCallback(element,item);
/// ADD, INSERT, UPDATE, REMOVE, CLEAR
ObservableList<T> where(bool test(final T element)) {
final newList = new ObservableList<T>();
onChange.listen((final ListChangedEvent event) {
if(event.changetype != ListChangeType.CLEAR && test(event.item)) {
// ignore: missing_enum_constant_in_switch
switch(event.changetype) {
case ListChangeType.ADD:
newList.add(event.item);
break;
case ListChangeType.INSERT:
//newList.insert(event.index,event.item);
newList.add(event.item);
_logger.info("Items1: ${newList.length}");
break;
// case ListChangeType.UPDATE:
// if(newList.contains(event.item)) {
// //final index = newList.
// newList.update(event., item)
// }
// newList.add(event.item);
// break;
case ListChangeType.REMOVE:
newList.remove(event.item);
break;
}
}
if(event.changetype == ListChangeType.CLEAR) {
newList.clear();
}
});
return newList;
}
//- private -----------------------------------------------------------------------------------
void _fire(final ListChangedEvent<T> event) {

0 comments on commit b490746

Please sign in to comment.