I am using Marko and am needing to access the window and viewport height. I need the height of a specific div, and the height of the viewport. This is typically achieved by something similar to this
var viewportHeight = window.innerHeight
var elementHeight = document.getElementById("#myDiv").clientHeight
Can I access window
and document
within a class like so?
class {
onCreate(){
var windowHeight = window.innerHeight
var elementHeight = document.getElementById("#myDiv").clientHeight
this.state = { winHeight: winHeight, elemHeight: elementHeight }
}
}
#myDiv
p -- ${state.winHeight}
p -- ${state.elemHeight}
I am getting errors:
ReferenceError: document is not defined
ReferenceError: window is not defined
What is the best way to access those values within my markup?
Marko components are designed to be rendered on both the server and the browser. Because of this, accessing window
/document
in onCreate
(and onRender
and onInput
) will throw errors on the server where these values don't exist.
Additionally, you can't measure the DOM nodes until they have been mounted to the document.
For these reasons, onMount
is probably the best place to put this logic. onMount
is only called in the browser and after the nodes exist in the DOM.
That does mean however, that your initial render won't be quite correct. You'll probably need to default state.winHeight
and state.elemHeight
to something. After the initial render, the measurements will be taken and your component will update to reflect the new values.
class {
onCreate() {
this.state = { winHeight:0, elemHeight:0 }
}
onMount() {
this.state.elemHeight = this.getEl("measure").clientHeight;
this.state.winHeight = window.innerHeight;
}
}
<div key="measure">
<p>Element ${state.elemHeight}!</p>
<p>Window ${state.winHeight}!</p>
</div>
Depending on what you're using these values for, this may be acceptable and mostly unnoticeable to your users. However, if updating these values causes things to visibly jump around, you might consider rendering a placeholder when these values aren't available instead.