Blogs > Tabs and Multifield in AEM
AEM Sites
Tabs and Multifield in AEM
| January 18, 2023Hi, happy to find you here. Welcome to another blog
Tabs and Multifield in AEM
We will be learning how tabs are created in a component and how do we handle multifield. Also we will be focusing upon some more annotations of sling model. Here we have taken a small example of authoring product details like product name, description and product quantity. Here is the simple outlook of the dialog's xml which we are going to create in this blog. We have created a component called tabsandmultifielddemo where you can find the jcr:title and group as provided.
Tabs
In order to create tabs, you need to follow the following steps-
-
In items, create a node called tabs with sling:resourceType = granite/ui/components/coral/foundation/tabs
-
Then, create items and within items will reside your tabs, here tabone and tabtwo. the sling:resourceType for both will be same as provided, the jcr:title will differ. It will be Tab One and Tab Two respectively.
-
Now here you need to again add items within it columns within it again items and then columns and then in these items we can add our fields. This is because items define a container that can hold different components or fields. This allows you to structure the dialog in a hierarchical way, ensuring itโs organized and easier to manage. columns are used within items to organize fields in a specific layout (like multiple columns side by side), which is particularly useful when you want to present multiple fields on a single tab in an organized and visually appealing manner. Similarly, you need to create the same structure for tabtwo.
-
For tabone, in this the last items container node hence created, create 3 fields called productName, productPrice and productDescrition with the provided propertied.
Multifield
Since there could be a list of products with provided set of information and creating a component for each product scpecification is a bad idea, so aem provides a facility of creating a multifield for the same same.
Multifields allow authors to input a dynamic, flexible number of values in a single field. This is ideal for situations where the number of items is not fixed or known in advance. To create the multifield, follow the following steps.
-
Create a node called multifield with sling:resourceType = granite/ui/components/coral/foundation/form/multifield. Within multifield, create a node called field. The names must be same, the property name of field is important. Here we have named it as products.
-
Here you can find the properties to be added in multifield and field nodes.
-
Now create the productListNames, productListDescription and productListPrice as created for tabone. Ensure tehre are no duplicate names for any two widgets.
-
After creating the component, drag and drop it on a page, here we have added it on Test page. The dialog box of the component hence created will look like this.
Sling Model
Having authored values, we need to retrieve the values from backend. For this we need to create the sling model
package com.local.core.models;
import com.adobe.xmp.schema.service.StandardRelaxNGProvider;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import com.local.core.pojo.Products;
import org.apache.commons.math.analysis.solvers.BrentSolver;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.*;
import org.apache.sling.models.annotations.injectorspecific.Self;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;
@Model(adaptables = SlingHttpServletRequest.class)
public class TabAndMultifieldModel {
@Self
SlingHttpServletRequest request;
@Inject
@Via("resource")
@Named("productName")
@Required
String product;
@Inject
@Via("resource")
@Required
String productDescription;
@Inject
@Via("resource")
@Optional
@Default(values = "1")
String productPrice;
@Inject
@Via("resource")
@Optional
private List products;
String info;
@PostConstruct
protected void init() {
info = product + " || " + productDescription;
ResourceResolver resolver = request.getResourceResolver();
try{
PageManager pageManager = resolver.adaptTo(PageManager.class);
if(pageManager != null){
Page currentPage = pageManager.getContainingPage(request.getResource());
info = currentPage.getTitle() + " :: " + info;
}
}catch (Exception e){
e.printStackTrace();
}
}
public String getInfo() {
return info;
}
public String getProductDescription() {
return productDescription;
}
public String getProductPrice() {
return productPrice;
}
public String getProduct() {
return product;
}
public List getProducts() {
return products;
}
}
-
Here we have added SlingHttpServletRequest as adaptables, this is to recieve those objects which cannot be recieved directly from Resource.
-
@Inject is used to map the values for tabs and multifield exclusively.
-
@Via is here used to map the field through resource.
-
Here we have not added defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL, rather have added annotations @Required and @Optional here.
-
@Named is used to map the field name to a substitue name referred in the backend.
- To add the multifield, we need to create a pojo class annoted with model, having field names same as that of the name property and applied @Inject to it.
- Here the list of pojo needs to be named with that of the field name and here in our case it is products.
-
Here info string provides the collective values hence retrieved and processed from a method annoted with @PostConstruct, which gets called only after all the authoring is complete.
-
The values is hence recieved from Slightly using the following snippet in the .html file.
-
The final output looks like this:
package com.local.core.pojo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
import org.apache.sling.models.annotations.Model;
import javax.inject.Inject;
@Model(adaptables = Resource.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class Products {
@Inject
String productListName;
@Inject
String productListDescription;
@Inject
String productListPrice;
public String getProductListName() {
return productListName;
}
public String getProductListDescription() {
return productListDescription;
}
public String getProductListPrice() {
return productListPrice;
}
}
Conclusion
We have created a component having multifield and tabs. Also we have learnt some more annotaions, the role of pojo and how exactlymultifield and tabs are rendered.
I hope you enjoyed the learing and have found the blog informative.