In Ext JS 4, is there a simple way to determine if a component is actually in view? That is both visible and within the area currently displayed in the browser window.
I am aware of isVisible(), which will tell me if it is visible in the DOM, but I would also like to know if the component has been scrolled out of view (and therefore does not need updating visually).
You could use Component.getX(), Component.getY(), Component.getHeight(), Component.getWidth() of your main container and your component and compute that manually (also check the scroll methods of the main component).
Related
I have a TabView component that has multiple tabs containing components. These components have entire hierarchies of other components. How could I know from any child component nested arbitrarily deep in one of these hierarchies whether or not it's parent tab is in focus in the TabView?
Preferably, I would want to implement this similar to react-navigation's withNavigationFocus (or an equivalent hook) so that any component can know if it's in tab focus without having to pass props down the chain of components. I'm thinking you could have a TabViewContext that components can register themselves as focus listeners to by doing a useContext. The TabViewContext would be provided by the TabView and the TabView would be responsible for determining what registered listeners are in focus when tabs change. My dilemma is I don't know how the TabView could determine efficiently what nested child components come into focus when the tab changes. Any ideas?
In case the other parent tabs are hidden, you could test for visibility in plain JS, rather than have a much more complex solution...
Checkout this answer on how to do this.
So components that care about the visibility of their parent tab could use a ref for their own DOM elements and test whether they're visible or not. You could build this into a simple helper function or a hook
EDIT:
I'd suggest going with something like this:
Each Tab will provide a context with method for any descendant to register a callback that will be called when the Tab is hidden. The TabView can pass a "isVisible" prop to each tab (if it doesn't already), so Tab can know when its display changes.
When a Tab changes from visible to hidden. All registered callbacks will be called.
I would of course write a hook or a helper function to create this TabVisibilty context so each Tab component can use it in a reusable manner.
This Is more of a "theoretical" question that often buffles me in different situations and use cases, I will give a simple example to demonstrate it.
Let's say I have a list of 10 buttons.
Everrytime I click a button, a floating menu appears on top of the clicked button - there is only one menu visible for any given time.
Let's assume that I can't render this floating menu within the button component and I can only render it in the buttons parent level (meaning that this menu is sibling to those buttons).
I have 2 possible options to do that:
Keep the x,y position of the last clicked button and render the menu in this given position
Render the menu once and using "ref" to directly relocate the menu
On the one hand, the first approach seems more "Reactish". On the other hand, the possible implemention I can think of is pretty ugly (capturing the clicked item position and saving it to state which triggers defender), and further more, I am not so sure about re re rendering the whole container just because I need to move a small piece of it.
The second approach touches the DOM directly using refs. Although possible , doing DOM manipulations sometimes feel bad to me.
Is there a better approach? Which of the 2 makes more sense?
Any suggestion or thoughts will be appreciated!
Thanks
React uses whats called a virtual DOM, which is a representation of the DOM, that sits on top of the real browser DOM. Whenever you update state or a user performs an action the virtual DOM compares and checks the changes with the real DOM and then updates the UI accordingly.
So if certain DOM elements like a are not different between changes it does not get re rendered, only the DOM elements that have changed are re rendered. And if a property on a DOM element is changed, only the property is updated and the DOM element is not re rendered.
<div color="blue" />
to
<div color="red" />
The whole element is not destroyed and re created, only the property is changed.
However if the element in the host tree is different than the entire host tree is destroyed and recreated.
<div />
to
<p>
This is refereed to as reconciliation
https://reactjs.org/docs/reconciliation.html
So using refs is definitely more of a hacky solution since its more of an escape hatch and directly manipulates the DOM.
I would definitely stick with option 1, I think there is an elegant solution to the use case you described, it would involve just adding a click event listener in the componentDidMount and keeping track of the click position that way.
And also its hard to say without code but since your buttons will be the same, they will not be re rendered only the menu will.
Would recommend for further reading
https://overreacted.io/react-as-a-ui-runtime/
I know that i require foundation/components/parbase as a sling:resourceSuperType, as Parbase allows components to inherit attributes from other components.
As an Example, i removed parbase as resourceSuperType from foundation/components/image component and the dialog was not able to load properly as seen in the Screenshot, Crop, Rotate, Clear functionality is no longer working.
I've confirmed that Ext Js library is being loaded properly for xtype 'html5SmartImage', So what extra things does foundation/components/parbase provides for this functionality ?
Parbase allows components to inherit attributes from other components.
The above statement is a bit wrong in my opinion. It doesn't allow you to inherit attributes from other components. Rather any component which defines foundation/components/parbase as it's parent would inherit the scripts of parbase.
If you look at the parbase component within AEM, you would find a servlet which renders an image, when the URL contains img selector. Additionally you may also find a script that caters to the selector scaffolding.
Thus, whenever you define parbase or any other component inheriting from parbase as the super type for your component, you are able to use the image rendering features without the need to write separate logic for the same.
Coming to your example of the image component, the html5smartimage makes a request to the resource using the request suffix (.img.png), which is when your Image rendering servlet kicks in and draws the image. Since you have removed parbase from the super type, you would receive a 404 for the request thereby showing empty panel. However, the buttons displayed as disabled is altogether a different issue. It's a bug/feature in AEM, that when the requested image is not found, further processing of the panel stops thereby rendering them disabled.
I created a new component in my grid's listeners: beforeload, and when i called .show() on it, the debugger showed that d.ownerCt is undefined. Any suggestions?
ownerCt is set automatically by the framework as soon as a component is added to a container. It seems that you're calling show() manually indicating that your component is not part of a container hierarchy.
See ownerCt in the Ext JS documentation (here Ext JS 6 classic, but that concept hasn't changed).
This Component's owner Container (is set automatically when this
Component is added to a Container).
Important. This is not a universal upwards navigation pointer. It
indicates the Container which owns and manages this Component if any.
There are other similar relationships such as the button which
activates a menu, or the menu item which activated a submenu, or the
column header which activated the column menu.
These differences are abstracted away by the up method.
Note: to access items within the Container see itemId.
I've designed a pretty simple responsive layout (be sure to open link with Chrome) and now I'm trying to implement it in React. I've attached some screenshots of the layout as well.
This app is supposed to be the typical tab/nav app, but due to the responsive layout, the view hierarchy is pretty awkward to work with in React.
I've built a React component called Layout to abstract away all the layout stuff. Layout also has props for renderLeft, renderRight, title, and onTab. Layout's children are then rendered into the content block.
The easy solution would be to make Layout a child of the current view and render whatever you want. However, this is going to mess up some animations I had in mind. I want to have a CSSTransitionGroup element wrapped around the tabbar, the title, and the left and right buttons animating them as they change. Thus, the Layout element must remain the same between the views else a new CSSTransitionGroup element will be rendered for each view which isn't good.
So now the problem is that I have a Layout component with a view rendered as its child (but sort of as sibling with respect to the App component), but the view needs to specify renderLeft, renderRight and title for the Layout which is its parent! For example, in the top-level App component, the render function may look like the following, and I need some way of setting Layout's renderLeft from the View.
render() {
return (
<Layout renderLeft={??}>
<View setRenderLeft={??}/>
<Layout/>
)
}
The only thing I've thought of so far seems totally like the wrong way of doing it:
In the top-level App component, have a state variables for renderLeft, renderRight, and title and App passes those to the Layout props. Now for the view, pass some functions like setRenderLeft, setRenderRight, and setTitle which will change the App state and thus change the Layout. We can thus call these functions in componentWillMount for each view.
This just seems like a total hack and seems to break the whole idea of one-directional-data-flow. However, I'm not sure how else to do it! Are there any more proper ways of doing this? I'm reminded of the concept of delegation when building iOS apps, but thats very OOP and not very FP.
Any ideas?
Your question is a little difficult to tell exactly what the issue is, however if I were you I would read up on https://facebook.github.io/react/tips/communicate-between-components.html
For communication between two components that don't have a
parent-child relationship, you can set up your own global event
system. Subscribe to events in componentDidMount(), unsubscribe in
componentWillUnmount(), and call setState() when you receive an event.
Flux pattern is one of the possible ways to arrange this.
You want to either have the siblings talk to the parent and communicate there, or at the global level.
Hope this helps.