Skip to content

Commit

Permalink
fix(dropdown): restore dropdown content location in DOM
Browse files Browse the repository at this point in the history
This fixes scenarios when a dropdown reattached, e.g. with `if.bind`
  • Loading branch information
MaximBalaganskiy committed Apr 15, 2020
1 parent 38ef432 commit e99b4cb
Showing 1 changed file with 121 additions and 118 deletions.
239 changes: 121 additions & 118 deletions src/dropdown/dropdown.ts
Original file line number Diff line number Diff line change
@@ -1,118 +1,121 @@
import * as au from "../aurelia";

@au.customAttribute("md-dropdown")
@au.autoinject
export class MdDropdown {
constructor(private element: Element) {
this.attributeManager = new au.AttributeManager(this.element);
}

static elementId: number = 0;
id: string;
attributeManager: au.AttributeManager;
contentAttributeManager: au.AttributeManager;

@au.bindable({ defaultBindingMode: au.bindingMode.oneTime })
activates = "";

@au.bindable({ defaultBindingMode: au.bindingMode.oneTime })
ref: Element = null;

@au.ato.bindable.stringMd({ defaultBindingMode: au.bindingMode.oneTime })
alignment: "left" | "right";

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
autoTrigger: boolean;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
constrainWidth: boolean;

@au.bindable({ defaultBindingMode: au.bindingMode.oneTime })
container: Element | string;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
coverTrigger: boolean;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
closeOnClick: boolean;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
hover: boolean;

@au.ato.bindable.stringMd({ defaultBindingMode: au.bindingMode.oneTime })
mdTitle: string;

@au.ato.bindable.numberMd({ defaultBindingMode: au.bindingMode.oneTime })
inDuration: number;

@au.ato.bindable.numberMd({ defaultBindingMode: au.bindingMode.oneTime })
outDuration: number;

instance: M.Dropdown;

attached() {
this.handleActivateElement();
this.contentAttributeManager = new au.AttributeManager(document.getElementById(this.activates));
this.attributeManager.addClasses("dropdown-trigger");
this.contentAttributeManager.addClasses("dropdown-content");
let container = typeof this.container === "string" ? document.querySelector(this.container) : this.container;
let options: Partial<M.DropdownOptions> = {
alignment: this.alignment,
autoTrigger: this.autoTrigger,
constrainWidth: this.constrainWidth,
container,
coverTrigger: this.coverTrigger,
closeOnClick: this.closeOnClick,
hover: this.hover,
inDuration: this.inDuration,
outDuration: this.outDuration,
onOpenStart: () => au.fireMaterializeEvent(this.element, "open-start"),
onOpenEnd: () => au.fireMaterializeEvent(this.element, "open-end"),
onCloseStart: () => au.fireMaterializeEvent(this.element, "close-start"),
onCloseEnd: () => au.fireMaterializeEvent(this.element, "close-end")
};
au.cleanOptions(options);
this.instance = new M.Dropdown(this.element, options);
}

detached() {
if (this.instance) {
this.instance.destroy();
this.instance.dropdownEl.remove();
}
this.attributeManager.removeAttributes("data-target");
this.attributeManager.removeClasses("dropdown-trigger");
this.contentAttributeManager.removeClasses("dropdown-content");
}

open() {
if (this.instance) {
this.instance.open();
}
}

close() {
if (this.instance) {
this.instance.close();
}
}

recalculateDimensions() {
if (this.instance) {
this.instance.recalculateDimensions();
}
}

handleActivateElement() {
if (this.ref) {
let id = this.ref.getAttribute("id");
if (!id) {
id = `md-dropdown-${MdDropdown.elementId++}`;
this.ref.setAttribute("id", id);
this.activates = id;
}
this.id = id;
}
this.attributeManager.addAttributes({ "data-target": this.activates });
}
}
import * as au from "../aurelia";

@au.customAttribute("md-dropdown")
@au.autoinject
export class MdDropdown {
constructor(private element: Element) {
this.attributeManager = new au.AttributeManager(this.element);
}

static elementId: number = 0;
id: string;
attributeManager: au.AttributeManager;
contentAttributeManager: au.AttributeManager;

@au.bindable({ defaultBindingMode: au.bindingMode.oneTime })
activates = "";

@au.bindable({ defaultBindingMode: au.bindingMode.oneTime })
ref: Element = null;

@au.ato.bindable.stringMd({ defaultBindingMode: au.bindingMode.oneTime })
alignment: "left" | "right";

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
autoTrigger: boolean;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
constrainWidth: boolean;

@au.bindable({ defaultBindingMode: au.bindingMode.oneTime })
container: Element | string;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
coverTrigger: boolean;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
closeOnClick: boolean;

@au.ato.bindable.booleanMd({ defaultBindingMode: au.bindingMode.oneTime })
hover: boolean;

@au.ato.bindable.stringMd({ defaultBindingMode: au.bindingMode.oneTime })
mdTitle: string;

@au.ato.bindable.numberMd({ defaultBindingMode: au.bindingMode.oneTime })
inDuration: number;

@au.ato.bindable.numberMd({ defaultBindingMode: au.bindingMode.oneTime })
outDuration: number;

instance: M.Dropdown;
dropdownContentParent: HTMLElement;

attached() {
this.handleActivateElement();
const dropdownContent = document.getElementById(this.activates);
this.contentAttributeManager = new au.AttributeManager(dropdownContent);
this.attributeManager.addClasses("dropdown-trigger");
this.contentAttributeManager.addClasses("dropdown-content");
let container = typeof this.container === "string" ? document.querySelector(this.container) : this.container;
let options: Partial<M.DropdownOptions> = {
alignment: this.alignment,
autoTrigger: this.autoTrigger,
constrainWidth: this.constrainWidth,
container,
coverTrigger: this.coverTrigger,
closeOnClick: this.closeOnClick,
hover: this.hover,
inDuration: this.inDuration,
outDuration: this.outDuration,
onOpenStart: () => au.fireMaterializeEvent(this.element, "open-start"),
onOpenEnd: () => au.fireMaterializeEvent(this.element, "open-end"),
onCloseStart: () => au.fireMaterializeEvent(this.element, "close-start"),
onCloseEnd: () => au.fireMaterializeEvent(this.element, "close-end")
};
au.cleanOptions(options);
this.dropdownContentParent = dropdownContent.parentElement;
this.instance = new M.Dropdown(this.element, options);
}

detached() {
if (this.instance) {
this.instance.destroy();
this.dropdownContentParent.appendChild(this.instance.dropdownEl);
}
this.attributeManager.removeAttributes("data-target");
this.attributeManager.removeClasses("dropdown-trigger");
this.contentAttributeManager.removeClasses("dropdown-content");
}

open() {
if (this.instance) {
this.instance.open();
}
}

close() {
if (this.instance) {
this.instance.close();
}
}

recalculateDimensions() {
if (this.instance) {
this.instance.recalculateDimensions();
}
}

handleActivateElement() {
if (this.ref) {
let id = this.ref.getAttribute("id");
if (!id) {
id = `md-dropdown-${MdDropdown.elementId++}`;
this.ref.setAttribute("id", id);
this.activates = id;
}
this.id = id;
}
this.attributeManager.addAttributes({ "data-target": this.activates });
}
}

0 comments on commit e99b4cb

Please sign in to comment.