I'm learning Angular and there is something I dont really understand. My Application works fine on all browser (Chrome, Firefox, Brave, Opera, mobile version also) except Safari (desktop and mobile). My app launches great except for my script from the assets folder. ("src/assets").
angular.json
...
"scripts": ["src/assets/js/layout.js"]
...
layout.js
'use strict';
var layoutInit = function layoutInit(){
const header = document.querySelector("header")// return null on safari;
const main = document.querySelector("main") // return null on safari;
const footer = document.querySelector("footer") // return null on safari;
function resize(){
main.style.minHeight = window.innerHeight - (footer?.offsetHeight ?? 0) + "px";
main.style.paddingTop = (header?.offsetHeight ?? 0) + "px";
}
window.onresize = resize;
resize();
}
if(document.readyState === 'loading' || document.readyState === 'interactive'){
document.addEventListener('DOMContentLoaded', layoutInit)
}else{
layoutInit()
}
Safari version : 15.6.1 Angular : 15
Does anyone experienced this issue ?
First off: I can't answer the question. My guess is something to do with how/when Safari loads scripts?
However, I'd rather suggest alternatives as a better practice over what you currently have (unless you have it for a particularly good reason?); It is odd to have a lovely Angular SPA that can do everything you want, but then use an outside script to just set out the page layout.
Assuming you have a basic
app.component.html
that looks suspiciously like this currently:Add in some view child usage:
So they can be accessed in the
app.component.ts
:And then handle your resize in there too:
Something like that; might look a little different but that's a you problem not a me problem.
Probably want to put in either an
ngOnInit
or likely anngAfterViewInit
method to call that so it's all set up on first load (otherwise it'll ONLY be triggered on window resizing)...That gets rid of your additional script and keeps it fully contained inside the app itself - triggered once when the app (view) is first initialised, and then subsequently after any window resizing is done.
That's a lot of effort for something that CSS can do, though.
My preference is to use Angular flex layout rather than raw CSS because 1) it's easier and 2) I personally like to keep base page structural details with the base page itself (the HTML).
Because of that, my memory for base CSS flex details is pretty poor, so I'll give it to you in AFL form in the template:
So long as you appropriately set up your html/body styling to flex layout, this will:
body { width: 100vw; height: 100vh; }
then app-container now fills the whole of the window)Followed by the children:
There's some additional things needed to make it work a little nicer and work exactly how you want it to (e.g.
#main { overflow: auto; }
) but that gets you 90% of the way there with the layout you want and there's no actual scripting involved, just CSS.