EDIT [resolved]
based on the answer from Thingamabobs below, the approach simply turns out to be making sure the elements you spawn are allocated to correct parents.
It is worthwhile to create a frame just to hold every scrollable element since you can't move widgets around between parents when using pack/place. So a common parents between all movable elements will give you the freedom to move them around, again just create a holder frame. See the answer and discussion below for more details.
EDIT2
Bryan's answer below has very good info and an alternate approach using just a canvas. The core concepts still stand the same.
original question begins here
The situation
So based on this answer by Bryan, I used this approach to spawn widgets on a scrollable frame (which is basically a Canvas wrapping a frame inside as we know cause Frames don't have scroll attributes).
The widgets in this case are just tk.Buttons which I spawn in a loop using lambda to preserve state. That aspect is completely fine.
The issue
Now everything works fine except when I spawn more elements (again just buttons), they seem to be cut off. and I can't seem to scroll down to see the remaining ones. I am only able to scroll upwards only to see empty space.
please see the video below to see what I mean (excuse my horrible color choices, this is for a quick demo)
In the video, there are more elements below template47 but I can not scroll to them. I can scroll upwards but it's just lonely up there. All the names are actually buttons with zero bd and HLthickness.
what I have tried
To begin, my first instinct was to attach a ttk.scrollbar to the canvas+frame, which I did but observed the exact same behavior.
Then I tried to see if i could use .moveTo('1.0') to scroll down to last entry and then since upward scrolling works already, shouldn't have an issue. But this didn't do anything either. Still the elements were cut off, and it obviously messed up upward scrolling too.
I don't think I can use pack/grid geoManagers since as the answer by bryan i linked to above suggests, using place with its in_ arg is the preferred way. If it is possible otherwise, let me know though.
my use case in a nutshell
as depicted in the answer linked above, I also have two frames, and I'm using the on_click callback function to switch parents (a lot like in example code in answer). Turned out place was the best bet to achieve this. and it is, all of that aspect is working well. It's just the scroll thingy which doesn't work.
some code (dare i say MCVE)
how i bind to mousewheel
def _bound_to_mousewheel(self, event):
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
def _unbound_to_mousewheel(self, event):
self.canvas.unbind_all("<MouseWheel>")
def _on_mousewheel(self, event):
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
creating the window
self.canvas.create_window((5, 6), window=self.scrolled_frame, anchor="w")
ad of course the widgets inside
for f in self.fav_templates:
btn = tk.Button(self.root, text='text', command=lambda te=f: self._on_click(te))
btn.place(in_=self.ft_frame, x=20, y=p)
So
I'm sure above snippets would give idea of what I've done. If someone needs me to create a complete MCVE they can run, happy to do that, lemme know.
What did I miss in the setup? any ideas or suggestion are welcome.
Thank You :)

