I'm building a drag-and-drop workspace, similar to the ones you find for making mockups. I have a workspace custom element that has a larger, nested element that can be zoomed and panned. Therefore, I need to carefully track size and position data of the workspace and all contained elements.
In my attached event of my custom element, I programatically set the height and width of the workspace as a JavaScript object, which is bound to the css in the view:
workspaceCustomElement.js
export class WorkspaceCustomElement {
constructor(element) {
this.element = element;
}
attached() {
this.workspace.size = {
height: this.element.height * 5,
width: this.element.width * 5
}
}
}
workspaceCustomElement.html
<div css="height: ${workspace.height}px; width: ${workspace.width}px;
left: ${(element.clientWidth - workspace.width)/2}px;
top: ${(element.clientHeight - workspace.height)/2}px;"></div>
Now I'm running into problems trying to grab the positions of my child elements. I have attached callbacks on them as well, but they are being evaluated before the attached callback above, and so the css binding hasn't been evaluated, and the size and positions are wrong.
I need to add a callback after the attached()
has been evaluated and the bindings have been updated. I can accomplish this by using a setTimeout
hack, but I have no confidence that this will always work.
attached() {
this.workspace.size = {
height: this.element.height * 5,
width: this.element.width * 5
}
setTimeout(() => {
let components = this.element.querySelectorAll('.component');
Array.prototype.forEach.call(components, (component) => {
let model = component.model;
model.position = {
x: component.clientLeft,
y: component.clientTop
};
}
}, 0)
}
Is there a better, more reliable way to queue an instruction after the next binding update?