Wednesday, May 18, 2022

Uncaught TypeError: Cannot read properties of undefined (reading 'add') - React Helmet

 I was getting the below error while using the react-helmet to dynamically change the head section - meta tags, title etc, also the pages were not loading.

scheduler.development.js:171 Uncaught TypeError: Cannot read properties of undefined (reading 'add')

    at e.r.init (Dispatcher.js:53:1)

    at e.r.render (Dispatcher.js:67:1)

    at finishClassComponent (react-dom.development.js:17485:1)

    at updateClassComponent (react-dom.development.js:17435:1)

    at beginWork (react-dom.development.js:19073:1)

    at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)

    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)

    at invokeGuardedCallback (react-dom.development.js:4056:1)

    at beginWork$1 (react-dom.development.js:23964:1)

    at performUnitOfWork (react-dom.development.js:22776:1)

    at workLoopSync (react-dom.development.js:22707:1)

    at renderRootSync (react-dom.development.js:22670:1)

    at performSyncWorkOnRoot (react-dom.development.js:22293:1)

    at react-dom.development.js:11327:1

    at unstable_runWithPriority (scheduler.development.js:468:1)

    at runWithPriority$1 (react-dom.development.js:11276:1)

    at flushSyncCallbackQueueImpl (react-dom.development.js:11322:1)

    at workLoop (scheduler.development.js:417:1)

    at flushWork (scheduler.development.js:390:1)

    at MessagePort.performWorkUntilDeadline (scheduler.development.js:157:1)


To fix the issue

Replaced react-helmet with  react-helmet-async

npm install react-helmet-async or yarn add react-helmet-async

Wrap the App element with HelmetProvider

import { HelmetProvider } from 'react-helmet-async';

ReactDOM.render(

  <React.StrictMode>

  <HelmetProvider>

    <App />

 </HelmetProvider>

  </React.StrictMode>,

  document.getElementById('root')

);

Now the helmet can be used in individual components to change the dynamic header elements

import { Helmet } from 'react-helmet';

import {  Test   } from './components';

const Test = () => {

  return (

<React.Fragment>

<Helmet>

<title>Test</title>

<meta name="description" content="Test Description" />

<meta property="og:title" content="Test"/>

<meta property="og:description" content="Test" />

  </Helmet>

  <Introduction />

  <Details />

  <BackToTop />

</React.Fragment>

  );

};

export default Test;

After this, I saw the behavior, non of the existing meta tags defined in index.html apart from the title, replaced with the new values. To fix that, I added data-rh="true" to the metatags in index.html that require the change.

<meta property="og:title" content="default value" data-rh="true" />

Somehow data-react-helmet=" true"  property was not working.

Happy Coding!!!


Tuesday, May 10, 2022

How to Share Selected i18n Dictionaries in JSON Format — AEM(Adobe Experience Manager)

 The AEM internationalization framework(i18n) uses dictionaries in the repository to store English strings and their translations in other languages. The framework uses English as the default language. Localized strings can be stored in several dictionaries in the repository, e.g., component level. The AEM internationalization framework combines the dictionaries and makes them available in Sling as a single ResourceBundle object. The i18n can be used in slightly, JavaScript, and Java to display the language-specific labels and values.

ResourceBundleExportServlet:

http://localhost:4502/libs/cq/i18n/dict.de_de.json
http://localhost:4502/libs/cq/i18n/dict.de.json
http://localhost:4502/libs/cq/i18n/dict.fr_fr.json

Client library JSON:

Custom servlet with sling:basename:

http://localhost:4502/bin/fetchi18nvalues/search.it.json
http://localhost:4502/bin/fetchi18nvalues/search.bg.json
http://localhost:4502/bin/fetchi18nvalues/search1.it.json
http://localhost:4502/bin/fetchi18nvalues/search1.bg.json



Friday, May 6, 2022

How to limit the number of components in Container Components?

 In this post, let us see the approaches to limit the components in container components; in some cases, we may have the use case to limit the number of child components allowed to be added into the container due to the business rules.

Option1 — Limit through FE logic:

Option2 — Limit through Edit Config Listeners and Back End Servlet:

function(childEditable) {var path = childEditable.path;
var date = new Date();
var servletURL = '/bin/ComponentLimiterSevlet?' + date.getTime();
var requestData = 'componentPath=' + path;
$.ajax({
async: false,
type: 'GET',
url: servletURL,
dataType: 'text',
data: requestData,
success: function(returnData) {
if (returnData == 'false') {
var cmp = childEditable.getParent();
cmp.refresh();
showErrorAlert('Cannot drop more component, if you want to add more, please set the Max component allowed bigger.', 'Error');
}
}
})
function showErrorAlert(message, title) {
var fui = $(window).adaptTo("foundation-ui"),
options = [{
text: "OK",
warning: true
}];
message = message || "Unknown Error";
title = title || "Error";
fui.prompt(title, message, "error", options);
}
}
import java.io.IOException;import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Session;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.servlets.annotations.SlingServletPaths;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.propertytypes.ServiceDescription;
import com.day.cq.wcm.api.policies.ContentPolicy;
import com.day.cq.wcm.api.policies.ContentPolicyManager;
@Component(service = { Servlet.class })
@SlingServletPaths("/bin/ComponentLimiterSevlet")
@ServiceDescription("Component Limitor Servlet")
public class ComponentLimitorServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 1L;
private String responseMsg = "true";
@Override
protected void doGet(final SlingHttpServletRequest req, final SlingHttpServletResponse resp)
throws ServletException, IOException {
try {
String currentComponentPath = req.getParameter("componentPath");
String resourcePath = currentComponentPath.substring(0, currentComponentPath.lastIndexOf("/"));
ResourceResolver resolver = req.getResourceResolver();Node resourceNode = JcrUtils.getNodeIfExists(resourcePath, resolver.adaptTo(Session.class));if (resourceNode != null) {
int maxComponents = 1;
ContentPolicyManager policyManager = resolver.adaptTo(ContentPolicyManager.class);if (policyManager != null) {
ContentPolicy contentPolicy = policyManager.getPolicy(resolver.getResource(resourcePath));
if (contentPolicy != null && contentPolicy.getProperties().containsKey("maxComponents")) {
maxComponents = Integer
.parseInt(contentPolicy.getProperties().get("maxComponents", String.class));
}
}
int toalComponentCount = 0;
NodeIterator iterator = resourceNode.getNodes();
while (iterator.hasNext()) {
iterator.next();
toalComponentCount++;
}
if (toalComponentCount > maxComponents) {
// Gets currently inserted node
Node currentComponentNode = JcrUtils.getNodeIfExists(currentComponentPath,
resolver.adaptTo(Session.class));
currentComponentNode.remove();
currentComponentNode.getSession().save();
responseMsg = "false";
} else {
responseMsg = "true";
}
}
} catch (Exception e) {
responseMsg = "true";
}
resp.getWriter().print(responseMsg);
}
}