Permalink
Browse files

fixes: #24 - Dialog loses focus

  • Loading branch information...
MikeMitterer committed Oct 20, 2015
1 parent 85b41c9 commit 839869d5b59e8407c69544d5fcb11324d99c81b0
View
@@ -42,5 +42,5 @@ part "src/dialog/MaterialNotification.dart";
part "src/dialog/components/MaterialDialogComponent.dart";
void registerMdlDialogComponents() {
registerMaterialDialogComponent();
_registerMaterialDialogComponent();
}
View
@@ -111,4 +111,5 @@ void inject(Function fn) {
*/
void tearDownInjector() {
_mdlInjector = null;
}
}
@@ -42,3 +42,4 @@ part of mdlapplication;
abstract class ScopeAware {
Scope get scope;
}
@@ -109,7 +109,6 @@ class MaterialTextfield extends MdlComponent {
/// Update text field value.
void change(final String value) {
if (value != null && value != _relaxedInput.value) {
int selStart = (_relaxedInput).selectionStart;
@@ -45,3 +45,23 @@ part of mdlcore;
class MaterialApplication {
void run() {}
}
/**
* MdlComponent that has a "refresh" Functions.
* Best way to invoke this function is via [refreshComponentsInSubtree]
*
* Sample-Component:
* [MaterialModel]
*/
abstract class RefreshableComponent {
void refresh();
}
/**
* For Components like [_MaterialDialogComponent] where it's necessary to
* change the ParentScope on runtime. For example if [MaterialDialog] pops up
* the Parent-Scope is set to the new Dialog
*/
abstract class HasDynamicParentScope {
void set parentScope(final Object parent);
}
View
@@ -102,4 +102,59 @@ bool isMdlWidget(final dom.HtmlElement element) {
Validate.notNull(element);
var jsElement = new JsObject.fromBrowserObject(element);
return jsElement.hasProperty(_MDL_WIDGET_PROPERTY);
}
/// Checks if [element] is a "MDLComponent"
bool isMdlComponent(final dom.HtmlElement element) {
Validate.notNull(element);
var jsElement = new JsObject.fromBrowserObject(element);
return jsElement.hasProperty(MDL_COMPONENT_PROPERTY);
}
/// Gives you all the component names registered for this [element]
List<String> mdlComponentNames(final dom.HtmlElement element) {
Validate.notNull(element);
final List<String> names = new List<String>();
var jsElement = new JsObject.fromBrowserObject(element);
if(!jsElement.hasProperty(MDL_COMPONENT_PROPERTY)) {
return names;
}
names.addAll((jsElement[MDL_COMPONENT_PROPERTY] as String).split(","));
return names;
}
/// Returns all the MDL-Components registered for this [element]
List<MdlComponent> mdlComponents(final dom.HtmlElement element) {
Validate.notNull(element);
final List<MdlComponent> components = new List<MdlComponent>();
if(!isMdlComponent(element)) {
return components;
}
var jsElement = new JsObject.fromBrowserObject(element);
final List<String> names = mdlComponentNames(element);
names.forEach((final String name) {
if(jsElement.hasProperty(name)) {
components.add(jsElement[name] as MdlComponent);
}
});
return components;
}
void refreshComponentsInSubtree(final dom.HtmlElement element) {
if(element != null && element is dom.HtmlElement) {
element.children.forEach((final dom.Element element) => refreshComponentsInSubtree(element));
if(isMdlComponent(element)) {
mdlComponents(element).forEach((final MdlComponent component) {
if(component is RefreshableComponent) {
(component as RefreshableComponent).refresh();
}
});
}
}
}
@@ -122,7 +122,7 @@ abstract class MaterialDialog extends Object with TemplateComponent implements S
Future<MdlDialogStatus> show({ final Duration timeout,void dialogIDCallback(final String dialogId) }) {
Validate.isTrue(_completer == null);
_logger.info("show start");
_logger.fine("start start...");
_completer = new Completer<MdlDialogStatus>();
@@ -141,23 +141,20 @@ abstract class MaterialDialog extends Object with TemplateComponent implements S
}
// Now - add the template into the _dialogContainer
_renderer.render().then((_) {
_renderer.render().then( (_) {
// _autoIncrementID must be on top of this block! - will be used by _elementID
_autoIncrementID = idCounter;
if(dialogIDCallback != null) {
dialogIDCallback(hashCode.toString());
}
final dom.HtmlElement dialog = _dialogContainer.children.last;
dialog.id = _elementID;
final MaterialDialogComponent dialogComponent = MaterialDialogComponent.widget(dialog);
if(dialogComponent != null) {
dialogComponent.scope = this;
_logger.shout("DC found!!!!");
} else {
_logger.shout("DC found!!!!");
final _MaterialDialogComponent dialogComponent = _MaterialDialogComponent.widget(dialog);
Validate.notNull(dialogComponent,"${dialog} must be a '_MaterialDialogComponent' (mdl-dialog class)");
dialogComponent.parentScope = this;
if(dialogIDCallback != null) {
dialogIDCallback(hashCode.toString());
}
_dialogContainer.classes.remove(_cssClasses.IS_HIDDEN);
@@ -177,7 +174,7 @@ abstract class MaterialDialog extends Object with TemplateComponent implements S
}
idCounter++;
_logger.info("show end (Dialog is rendered (ID: ${_elementID}))");
_logger.fine("show end (Dialog is rendered, got ID: ${_elementID})!");
});
return _completer.future;
@@ -297,7 +294,7 @@ abstract class MaterialDialog extends Object with TemplateComponent implements S
dom.HtmlElement container = _container;;
if(container == null) {
_logger.info("Container ${_containerClass} not found, create a new one...");
_logger.fine("Container ${_containerClass} not found, creating a new one...");
container = new dom.DivElement();
container.classes.add(_containerClass);
container.classes.add(_cssClasses.IS_DELETABLE);
@@ -33,74 +33,78 @@ class _MaterialDialogComponentConstant {
static const String WIDGET_SELECTOR = "mdl-dialog";
const _MaterialDialogComponentConstant();
}
/// Basic DI configuration for this Component or Service
/// Usage:
/// class MainModule extends di.Module {
/// MainModule() {
/// install(new MaterialDialogComponentModule());
/// }
/// }
class MaterialDialogComponentModule extends di.Module {
MaterialDialogComponentModule() {
// bind(DeviceProxy);
}
}
}
class MaterialDialogComponent extends MdlComponent implements ScopeAware {
/**
* Private Component!
* Necessary to change the parent-scope in [MaterialDialog#show]
* Marked as MdlComponentModel to keep the name in Dart2JS
*
* The name is checked in [MaterialModel] (
*/
class _MaterialDialogComponent extends MdlComponent implements ScopeAware, HasDynamicParentScope {
final Logger _logger = new Logger('mdldialog.MaterialDialogComponent');
//static const _MaterialDialogComponentConstant _constant = const _MaterialDialogComponentConstant();
static const _MaterialDialogComponentCssClasses _cssClasses = const _MaterialDialogComponentCssClasses();
Scope _scope;
MaterialDialogComponent.fromElement(final dom.HtmlElement element,final di.Injector injector)
_MaterialDialogComponent.fromElement(final dom.HtmlElement element,final di.Injector injector)
: super(element,injector) {
_scope = new Scope(this, mdlParentScope(this));
_init();
}
static MaterialDialogComponent widget(final dom.HtmlElement element) => mdlComponent(MaterialDialogComponent,element) as MaterialDialogComponent;
// Central Element - by default this is where mdl-dialog can be found (element)
// html.Element get hub => inputElement;
static _MaterialDialogComponent widget(final dom.HtmlElement element) => mdlComponent(element,_MaterialDialogComponent) as _MaterialDialogComponent;
// - EventHandler -----------------------------------------------------------------------------
void handleButtonClick() {
_logger.info("Event: handleButtonClick");
}
Scope get scope => _scope;
void set scope(final MaterialDialog dialog) {
/// The only reason for this class - makes it possible to update the parent-scope
/// when the Dialog pops up
/// Usage:
/// MaterialDialog#show() {
/// ...
/// _renderer.render().then( (_) {
/// ...
/// final dom.HtmlElement dialog = _dialogContainer.children.last;
/// dialog.id = _elementID;
///
/// final MaterialDialogComponent dialogComponent = MaterialDialogComponent.widget(dialog);
/// Validate.notNull(dialogComponent,"${dialog} must be a 'MaterialDialogComponent' (mdl-dialog class)");
///
/// dialogComponent.parentScope = this;
/// ...
/// }
/// }
@override
void set parentScope(final Object dialog) {
Validate.notNull(dialog);
Validate.isTrue(dialog is MaterialDialog);
_scope = new Scope(dialog,null);
refreshComponentsInSubtree(element);
}
//- private -----------------------------------------------------------------------------------
/// Nothing to do here - all the logic is in MaterialDialog and its children
void _init() {
_logger.info("MaterialDialogComponent - init");
// final dom.DivElement sample = new dom.DivElement();
// sample.text = "Your MaterialDialogComponent-Component works!";
// element.append(sample);
//
// element.classes.add(_cssClasses.IS_UPGRADED);
_logger.fine("_MaterialDialogComponent - init");
}
}
/// registration-Helper
void registerMaterialDialogComponent() {
final MdlConfig config = new MdlWidgetConfig<MaterialDialogComponent>(
/// Also private - _MaterialDialogComponent is only used internally by [MaterialDialog]
void _registerMaterialDialogComponent() {
final MdlConfig config = new MdlWidgetConfig<_MaterialDialogComponent>(
_MaterialDialogComponentConstant.WIDGET_SELECTOR,
(final dom.HtmlElement element,final di.Injector injector) => new MaterialDialogComponent.fromElement(element,injector)
(final dom.HtmlElement element,final di.Injector injector) => new _MaterialDialogComponent.fromElement(element,injector)
);
// If you want <mdl-dialog></mdl-dialog> set selectorType to SelectorType.TAG.
@@ -35,7 +35,7 @@ class _MaterialModelConstant {
const _MaterialModelConstant();
}
class MaterialModel extends MdlComponent {
class MaterialModel extends MdlComponent implements RefreshableComponent {
final Logger _logger = new Logger('mdldirective.MaterialModel');
//static const _MaterialModelConstant _constant = const _MaterialModelConstant();
@@ -51,26 +51,58 @@ class MaterialModel extends MdlComponent {
@override
void attached() {
_scope = new Scope(this, mdlParentScope(this));
_init();
try {
_init();
} on NoSuchMethodError catch(e,stacktrace) {
// It's possible that at this moment the requested fieldname is not yet available
// MaterialDialog is a candidate for this.
// If MaterialDialog pops up attached() is called but only then the parent-scope is set
// via dialogComponent.parentScope = this;
if(!_scope.parentContext is HasDynamicParentScope) {
_logger.shout(e.toString(),e,stacktrace);
}
}
}
@override
/// Called in [_MaterialDialogComponent] if parent changes ([MaterialDialog] sets itself as parent!!!)
void refresh() {
_logger.fine("MaterialModel - refresh");
// Most important part - check if there is a new parent
_scope = new Scope(this, mdlParentScope(this));
// Remove previously registered Streams!
downgrade();
// Re-Init
_setupObserver();
}
//- private -----------------------------------------------------------------------------------
void _init() {
_logger.info("MaterialModel - init");
_logger.fine("MaterialModel - init");
/// Recommended - add SELECTOR as class
element.classes.add(_MaterialModelConstant.WIDGET_SELECTOR);
final String fieldname = element.attributes[_MaterialModelConstant.WIDGET_SELECTOR].trim();
_setupObserver();
element.classes.add(_cssClasses.IS_UPGRADED);
}
/// Scope-Context is always the next (up the tree) ScopeAware parent
void _setupObserver() {
_scope.context = _scope.parentContext;
final ModelObserver observer = _observerFactory.createFor(element);
eventStreams.addAll(observer.observe(_scope,fieldname));
element.classes.add(_cssClasses.IS_UPGRADED);
eventStreams.addAll( observer.observe( _scope ,_fieldname));
}
String get _fieldname => element.attributes[_MaterialModelConstant.WIDGET_SELECTOR].trim();
}
/// registration-Helper
@@ -104,6 +104,6 @@ void configLogging() {
// now control the logging.
// Turn off all logging first
Logger.root.level = Level.FINE;
Logger.root.level = Level.INFO;
Logger.root.onRecord.listen(new LogConsoleHandler());
}
Oops, something went wrong.

0 comments on commit 839869d

Please sign in to comment.