Hello,
Does anyone know how to create a react component with responsive grid and options so that we can drag and add other additional components?
The goal for us is to create a popup component and within this popup component we are going to name the component within the options menu. In the meantime also has the ability to drag and add other react components we have created. The purpose of the Popup Name is to be able to pass the data into react and link it with other AEM React component so that it can be triggered with an event.
For example
1. Add a button component
2. within the button component, there a option we can indicate which popup should it open if a user clicks on it
3. once the user clicks on the button, it then looks for the popup component with the same name and the popup should be revealed.
4. within the popup we can add whatever the component we want, for example, video component or image component.
Problem:
1. I tried several ways of doing it, adding responsive grid from @adobe/aem-react-editable-components into the functional popup component we created, it didnt work.
2. we also tried creating a class based popup component which extents from the responsive grid, this works however when we try to add the options menu in by creating the java file and the .content.xml, we weren't able to add any of the components in(even though the options are there, but its not responding). However, the name of the popup component is being passed into React correctly.
when we console.log props, we do see the name of the component is being passed into react correctly along with other data
below are the xml files created
_cq_dialog is there for the option menu to work.
_cq_template, new, and _cq_editConfig is there for the responsive grid of adding additional components to work.
it works all fine, until we add the java files which handles the functionality of passing the data from the options menu into react
Note: I also see other people trying to achieve the same thing as us, but the solutions they get points them to the SPA documentation which did not mention any complex use case.
Solved! Go to Solution.
Hi,
you need to add java model as well for a container component
e.g.
package com.community.aemlab.spa.core.models.impl; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.inject.Inject; import org.apache.commons.lang3.ArrayUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Source; import org.apache.sling.models.annotations.injectorspecific.OSGiService; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import org.apache.sling.models.factory.ModelFactory; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import com.adobe.cq.export.json.SlingModelFilter; import com.adobe.cq.wcm.core.components.models.Container; import com.adobe.cq.wcm.core.components.models.ListItem; import com.community.aemlab.spa.core.models.CustomGrid; import com.day.cq.wcm.api.TemplatedResource; import com.day.cq.wcm.api.components.ComponentManager; import com.drew.lang.annotations.NotNull; @Model(adaptables = SlingHttpServletRequest.class, adapters = { CustomGrid.class, ComponentExporter.class }, resourceType = CustomGridImpl.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class CustomGridImpl implements CustomGrid, Container { static final String RESOURCE_TYPE = "aemlab-spa/components/custom/customgrid"; @Self private SlingHttpServletRequest request; @Inject @Source("script-bindings") Resource resource; @ValueMapValue private String gridLayout; @ValueMapValue private String title; @ValueMapValue private String description; @Override public String getDescription() { return description; } @Override public String getTitle() { return title; } @Override public String getGridLayout() { return gridLayout; } @Override public String getExportedType() { return CustomGridImpl.RESOURCE_TYPE; } /** * The model factory. */ @OSGiService protected ModelFactory modelFactory; /** * The sling model factory service. */ @OSGiService protected SlingModelFilter slingModelFilter; /** * The list of child items. */ protected List<ListItem> items; /** * The list of child resources that are components. */ protected List<Resource> childComponents; /** * The child resources to be exported. */ protected List<Resource> filteredChildComponents; /** * Map of the child items to be exported wherein the key is the child name, and the value is the child model. */ protected Map<String, ? extends ComponentExporter> itemModels; /** * The name of the child resources in the order they are to be exported. */ private String[] exportedItemsOrder; @NotNull @Override public Map<String, ? extends ComponentExporter> getExportedItems() { if (itemModels == null) { itemModels = getItemModels(request, ComponentExporter.class); } return itemModels; } @NotNull @Override public String[] getExportedItemsOrder() { if (exportedItemsOrder == null) { Map<String, ? extends ComponentExporter> models = getExportedItems(); if (!models.isEmpty()) { exportedItemsOrder = models.keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY); } else { exportedItemsOrder = ArrayUtils.EMPTY_STRING_ARRAY; } } return Arrays.copyOf(exportedItemsOrder, exportedItemsOrder.length); } /** * Get the models for the child resources as provided by {@link AbstractContainerImpl#getFilteredChildren()}. * * @param request The current request. * @param modelClass The child model class. * @return Map of models wherein the key is the child name, and the value is it's model. */ protected Map<String, ComponentExporter> getItemModels(@NotNull final SlingHttpServletRequest request, @NotNull final Class<ComponentExporter> modelClass) { Map<String, ComponentExporter> models = new LinkedHashMap<>(); getFilteredChildren().forEach(child -> { ComponentExporter model = modelFactory.getModelFromWrappedRequest(request, child, modelClass); if (model != null) { models.put(child.getName(), model); } }); return models; } /** * Return (and cache) the list of children resources that are components, filtered by the Sling Model Filter. This * should only be used for JSON export, for other usages refer to {@link AbstractContainerImpl#getChildren}. * * @return The list of children resources available for JSON export. */ @NotNull protected List<Resource> getFilteredChildren() { if (filteredChildComponents == null) { filteredChildComponents = new LinkedList<>(); slingModelFilter.filterChildResources(getChildren()) .forEach(filteredChildComponents::add); } return filteredChildComponents; } /** * Return (and cache) the list of children resources that are components * * @return List of all children resources that are components. */ @NotNull protected List<Resource> getChildren() { if (childComponents == null) { Resource effectiveResource = this.getEffectiveResource(); childComponents = Optional.ofNullable(request.getResourceResolver().adaptTo(ComponentManager.class)) .map(componentManager -> StreamSupport.stream(effectiveResource.getChildren().spliterator(), false) .filter(res -> Objects.nonNull(componentManager.getComponentOfResource(res)))) .orElseGet(Stream::empty) .collect(Collectors.toList()); } return childComponents; } /** * Get the effective {@link TemplatedResource} for the current resource. * * @return The TemplatedResource, or the current resource if it cannot be adapted to a TemplatedResource. */ @NotNull protected Resource getEffectiveResource() { if (this.resource instanceof TemplatedResource) { return this.resource; } return Optional.ofNullable((Resource)this.resource.adaptTo(TemplatedResource.class)) .orElse(Optional.ofNullable((Resource)this.request.adaptTo(TemplatedResource.class)) .orElse(this.resource)); } }
Hi,
you need to add java model as well for a container component
e.g.
package com.community.aemlab.spa.core.models.impl; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.inject.Inject; import org.apache.commons.lang3.ArrayUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.Source; import org.apache.sling.models.annotations.injectorspecific.OSGiService; import org.apache.sling.models.annotations.injectorspecific.Self; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import org.apache.sling.models.factory.ModelFactory; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import com.adobe.cq.export.json.SlingModelFilter; import com.adobe.cq.wcm.core.components.models.Container; import com.adobe.cq.wcm.core.components.models.ListItem; import com.community.aemlab.spa.core.models.CustomGrid; import com.day.cq.wcm.api.TemplatedResource; import com.day.cq.wcm.api.components.ComponentManager; import com.drew.lang.annotations.NotNull; @Model(adaptables = SlingHttpServletRequest.class, adapters = { CustomGrid.class, ComponentExporter.class }, resourceType = CustomGridImpl.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class CustomGridImpl implements CustomGrid, Container { static final String RESOURCE_TYPE = "aemlab-spa/components/custom/customgrid"; @Self private SlingHttpServletRequest request; @Inject @Source("script-bindings") Resource resource; @ValueMapValue private String gridLayout; @ValueMapValue private String title; @ValueMapValue private String description; @Override public String getDescription() { return description; } @Override public String getTitle() { return title; } @Override public String getGridLayout() { return gridLayout; } @Override public String getExportedType() { return CustomGridImpl.RESOURCE_TYPE; } /** * The model factory. */ @OSGiService protected ModelFactory modelFactory; /** * The sling model factory service. */ @OSGiService protected SlingModelFilter slingModelFilter; /** * The list of child items. */ protected List<ListItem> items; /** * The list of child resources that are components. */ protected List<Resource> childComponents; /** * The child resources to be exported. */ protected List<Resource> filteredChildComponents; /** * Map of the child items to be exported wherein the key is the child name, and the value is the child model. */ protected Map<String, ? extends ComponentExporter> itemModels; /** * The name of the child resources in the order they are to be exported. */ private String[] exportedItemsOrder; @NotNull @Override public Map<String, ? extends ComponentExporter> getExportedItems() { if (itemModels == null) { itemModels = getItemModels(request, ComponentExporter.class); } return itemModels; } @NotNull @Override public String[] getExportedItemsOrder() { if (exportedItemsOrder == null) { Map<String, ? extends ComponentExporter> models = getExportedItems(); if (!models.isEmpty()) { exportedItemsOrder = models.keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY); } else { exportedItemsOrder = ArrayUtils.EMPTY_STRING_ARRAY; } } return Arrays.copyOf(exportedItemsOrder, exportedItemsOrder.length); } /** * Get the models for the child resources as provided by {@link AbstractContainerImpl#getFilteredChildren()}. * * @param request The current request. * @param modelClass The child model class. * @return Map of models wherein the key is the child name, and the value is it's model. */ protected Map<String, ComponentExporter> getItemModels(@NotNull final SlingHttpServletRequest request, @NotNull final Class<ComponentExporter> modelClass) { Map<String, ComponentExporter> models = new LinkedHashMap<>(); getFilteredChildren().forEach(child -> { ComponentExporter model = modelFactory.getModelFromWrappedRequest(request, child, modelClass); if (model != null) { models.put(child.getName(), model); } }); return models; } /** * Return (and cache) the list of children resources that are components, filtered by the Sling Model Filter. This * should only be used for JSON export, for other usages refer to {@link AbstractContainerImpl#getChildren}. * * @return The list of children resources available for JSON export. */ @NotNull protected List<Resource> getFilteredChildren() { if (filteredChildComponents == null) { filteredChildComponents = new LinkedList<>(); slingModelFilter.filterChildResources(getChildren()) .forEach(filteredChildComponents::add); } return filteredChildComponents; } /** * Return (and cache) the list of children resources that are components * * @return List of all children resources that are components. */ @NotNull protected List<Resource> getChildren() { if (childComponents == null) { Resource effectiveResource = this.getEffectiveResource(); childComponents = Optional.ofNullable(request.getResourceResolver().adaptTo(ComponentManager.class)) .map(componentManager -> StreamSupport.stream(effectiveResource.getChildren().spliterator(), false) .filter(res -> Objects.nonNull(componentManager.getComponentOfResource(res)))) .orElseGet(Stream::empty) .collect(Collectors.toList()); } return childComponents; } /** * Get the effective {@link TemplatedResource} for the current resource. * * @return The TemplatedResource, or the current resource if it cannot be adapted to a TemplatedResource. */ @NotNull protected Resource getEffectiveResource() { if (this.resource instanceof TemplatedResource) { return this.resource; } return Optional.ofNullable((Resource)this.resource.adaptTo(TemplatedResource.class)) .orElse(Optional.ofNullable((Resource)this.request.adaptTo(TemplatedResource.class)) .orElse(this.resource)); } }
Hey, the problem is I did include the model java files for the component, and it doesn't seem to work, its either i can pass the props into the react component and responsive grid not able to render it or wasn't able to pass the data but grid showing properly.
Views
Replies
Total Likes
I have created a cared component here with card container, could you please check if that helps
https://github.com/arunpatidar02/aemaacs-spa-aemlab
Views
Likes
Replies