Placing a component inside of another in AEM 6.5.11 - aem

In HTL it is possible to insert a component inside of another componet by using
<sly data-sly-resource="${ #path=somePath, resourceType='path/to/other/component' }"></sly>
. Is there a way to do the same thing in React?
I have tried to use the '#adobe/aem-react-editable-components' package but I haven't had much luck.

First there is a huge line between React and the HTL components. HTL is server side, gets compiled into JSP resolved at server side and digested DOM gets rendered on browser.
React is client side. DOM is built on browser and then rendered.
If you are trying insert HTL component inside a React component, NO, you cannot.
If you want to output DOM from HTL to be inserted into React component, technically doable using dangerously SetInnerHTML, but not recommended. Instead you have to pass the content of HTL component as input props into the React component and BUILD the React component at clientside.
If you can share more context on what exactly you are trying todo with code snippet, can suggest how to achieve.

Related

Why insert style again on client-side when using ssr? (from MUI docs)

I was going through Mui's Server-side Rendering DOCS.
And It says to prevent FOUC, we should inject style to rendered HTML on server side.
This was very clear.
But after that, it says "On the client-side, the CSS will be injected a second time before removing the server-side injected CSS."
this is the part I don't get.
why should we inject CSS again on client-side if it's already injected server-side?
Is there any difference between client-side cache and server-side cache?
And what is benefit of doing this?
If I had to guess, it would be that if some new Material UI element appears during runtime, the client needs to be able to handle that. SSR after all is for the initial loading of the page. So basically it is client rerendered to allow being dynamic.
This however creates issues for me personally as well since the new tag overwrites my Tailwind . Am trying to figure out how to render the client version above/before the Tailwind one, hence is why your question popped up on Google.
Edit: If I remember correctly, I solved using emotion; https://emotion.sh/docs/ssr

How to create dropdown component with search box in ionic framework with react typescript?

Is there any way to customize IonSelect component, or to create some custom component which contains search box inside (on top of) it?
There is one ionic component IonSelectable for angular and this is exactly what I need in react typescript as well.
Here is link to installation and example: https://www.npmjs.com/package/ionic-selectable for this component. Here is also a link to github repo: https://github.com/eakoriakin/ionic-selectable.
Here is the picture how it looks like, and it is pretty amazing:
Does anyone know if something same/similar already exist for react typescript? Or, is there any one to create/solve this?

Conditionally include different clientlibs depending on the browser in AEM?

Is it possible to conditionally include different clientlibs based on the user agent of the browser?
IE
<sly data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html"
data-sly-call="${clientlib.js # categories='a'}"/>
Modern Browsers
<sly data-sly-use.clientLib="/libs/granite/sightly/templates/clientlib.html"
data-sly-call="${clientlib.js # categories='b'}"/>
AEM version: 6.3
If not, what are the other alternatives to achieve the same?
Note: I tried to get this check done in a sling rewriter server side but the problem is, with the dispatcher on, it will only hit AEM for the furst time and cache the html, any subsequent hit will not invoke any server side logic to render it. Hence, it has to be done client side IMO
For this you have to write custom clientlibs templates as described here : https://github.com/nateyolles/aem-clientlib-async.
And then in the WCMUse class you can check user agent and include clientlibs accordingly.
First of all, as you already pointed out correctly, you need asolution that works with the dispatcher cache. So Sightly is not an option.
Then, regarding the fact, that most AEM templates have paragraph systems with multiple possible components to be added to a page on the one hand and AEM clientlibs are build on a template level (and not on page level) you end up with a clientlib holding lots of unused JS and CSS most of the time, since you have to cover all the possible options of components used in your page and paragraph system.
With that in mind, clientlibs might not be a good option to be used after all.
Having static CSS and JS files in your AEM repo and referencing them client side based on a JS snippet will do the trick and - in most cases - you will not buy any side effects with that approach.
You can either:
Wrap your clientlibs with conditional comments: https://stackoverflow.com/a/11703767
Create a Use-Object that check the User-Agent header and exposes a method isIE that you can use to conditionally include the clientlibs with data-sly-test. Alternatively your Use-Object could just return the proper categiers based on user agent so you can have only one clientlib call.
You could use the <script module> and <script nomodule> to achieve that. The first one is ignored by older browsers and the second one by the modern ones. Similar to Vue's Modern Mode. Check: https://cli.vuejs.org/guide/browser-compatibility.html#modern-mode
More likely you would need some back-end to create your custom clientlib template.

cq:includeClientLib in AEM if included inside a component jsp and the component is present twice on the page

If we give cq:includeClientLib inside my component jsp and if we drag and drop the component twice on that page, will the clientlib gets loaded/included twice?
what will be the case if we do in Sightly way (data-sly-call="${clientlib.all # categories='somecategory'}") ?
And also what is the suggested method of including client libs, either create a clientlib specific to the component and load only for that component or include all the CSS and JS at a common clientlib and use it across?
No, the clientlib is only included once for a category.
This is by design as the HTL (and respective JSP tag) are evaluated during runtime and the processor keeps a map of categories that have already been included and does not include them again.
As #i.net mentioned, each category will only be included once. To answer your follow up question about the suggested method..
The best practice seems to be to define a client library for each component, which is then embedded into a "global" client library. That global client library will then be included within your page template.
/etc/designs/acme/clientlibs-all
categories=["acme-all"]
embed=[compA,compB]
/apps/acme/components/compA/clientlibs
categories=["compA"]
/apps/acme/components/compB/clientlibs
categories=["compB"]
The reason the global client library is located under /etc/designs is to prevent exposing /apps to the public. However, in AEM 6.3, you could make use of the allowProxy property to serve the code at /etc.designs/. This would then look like this:
/apps/acme/clientlibs/clientlibs-all
categories=["acme-all"]
embed=[compA,compB]
allowProxy=true
/apps/acme/components/compA/clientlibs
categories=["compA"]
/apps/acme/components/compB/clientlibs
categories=["compB"]
Adobe recently released a good tutorial of more recent best practices around client library structure: https://helpx.adobe.com/experience-manager/kt/sites/using/getting-started-wknd-tutorial-develop/part3.html

Get Reference to top level ReactJS Component

So I am trying to inject some javascript into a website to scrape some information. However, if I could get a reference to the react component my life would be made a lot easier. I have looked at several questions on Stackoverflow but nothing useful turned up:
Reactjs - Get a component from anywhere in the app
React - get React component from a child DOM element?
I realize that react is basically just rendering the DOM by using its internal state and so reversing the DOM is not an option. Moreover, since the javascript on the website isn't mine I can't exactly have a global reference to the React component when its created. What I would really like is to have the '$r' that the react chrome devtools provides when you choose a DOM element but without having to rely on the chrome extension. I guess my question really boils down to how can I get the same representation that the chrome dev tools does so that I can reference a react component without actually creating a global variable. Also note I don't really care about efficiency or best practices I just want the reference to the component the same way that the devtools does it.