Liferay Form in Custom Module

Liferay Forms are one of most powerful feature in Liferay with which we can create and edit form without code change. Today we will be seeing how to use Liferay Form in our Custom Module along with edit and update.

Step 1 . Create and Configure the Form  by referring the below url 
https://portal.liferay.dev/docs/7-2/user/-/knowledge_base/u/creating-and-managing-forms

Step 2 . Once a Form is generated, you can use the ID for referencing the form .

Step 3 . We will be creating a Liferay mvc Module which will render, add and edit this form.

Rendering the form use the below code 

public void doView(RenderRequest renderRequest, RenderResponse renderResponse)
            throws IOException, PortletException {

        long formInstanceRecordId = ParamUtil.getLong(renderRequest, "formInstanceRecordId");
        DDMFormInstanceRecord ddmFormInstanceRecord = null;

        if(formInstanceRecordId > 0) {
            ddmFormInstanceRecord = DDMFormInstanceRecordLocalServiceUtil.fetchDDMFormInstanceRecord(formInstanceRecordId);
        }
        
        DDMFormInstance ddmFormInstance =  DDMFormInstanceLocalServiceUtil.fetchDDMFormInstance(34296L);
        DDMStructureVersion ddmStructureVersion = null;
        String html = StringPool.BLANK;
        try {
            ddmStructureVersion = ddmFormInstance.getStructure().getLatestStructureVersion();
        } catch (PortalException e) {
            e.printStackTrace();
        }
        
        DDMForm ddmForm = ddmStructureVersion.getDDMForm();
        DDMFormLayout ddmFormLayout = null;
        
        try {
            ddmFormLayout = ddmStructureVersion.getDDMFormLayout();
        } catch (PortalException e) {
            e.printStackTrace();
        }
        
        DDMFormRenderingContext ddmFormRenderingContext =
                new DDMFormRenderingContext();

        ddmFormRenderingContext.setContainerId("ddmForm".concat(StringUtil.randomString()));
        
        if(Validator.isNotNull(ddmFormInstanceRecord)) {
            try {
                ddmFormRenderingContext.setDDMFormValues(ddmFormInstanceRecord.getDDMFormValues());
            } catch (PortalException e) {
                e.printStackTrace();
            }
        }else {
            ddmFormRenderingContext.setDDMFormValues(_ddmFormValuesFactory.create(renderRequest, ddmForm));       
        }
                
        HttpServletRequest httpServletRequest = PortalUtil.getHttpServletRequest(renderRequest);

        ddmFormRenderingContext.setHttpServletRequest(httpServletRequest);
        ddmFormRenderingContext.setHttpServletResponse(PortalUtil.getHttpServletResponse(renderResponse));
        ddmFormRenderingContext.setLocale(PortalUtil.getLocale(renderRequest));
        ddmFormRenderingContext.setPortletNamespace(renderResponse.getNamespace());
        ddmFormRenderingContext.setViewMode(true);
            
        try {
            html = _ddmFormRenderer.render(ddmForm, ddmFormLayout, ddmFormRenderingContext);
        } catch (DDMFormRenderingException e) {
            e.printStackTrace();
        }           
        renderRequest.setAttribute("formHtml", html);
            
        super.doView(renderRequest, renderResponse);
    }
     
     In view.js 
      
<portlet:actionURL var="saveFMURL" />

<aui:form action="${saveFMURL}"  method="POST">
    ${formHtml}

    <aui:button type="submit" value="save"/>

</aui:form>  

Note - 34296L which ddmFormIntanceId can be referred  by giving option in configuration or taking input from  user also ,For this example i am Hard cording .
 

Adding , Editing the Form use the below code public void processAction(ActionRequest actionRequest, ActionResponse actionResponse)
                throws IOException, PortletException {
            
            ServiceContext serviceContext = null;
            long formInstanceRecordId = ParamUtil.getLong(actionRequest, "formInstanceRecordId");

            DDMFormInstance ddmFormInstance =  DDMFormInstanceLocalServiceUtil.fetchDDMFormInstance(34296L);
            DDMStructureVersion ddmStructureVersion = null;
            try {
                ddmStructureVersion = ddmFormInstance.getStructure().getLatestStructureVersion();
            } catch (PortalException e) {
                e.printStackTrace();
            }
            
            DDMForm ddmForm = ddmStructureVersion.getDDMForm();
            DDMFormValues ddmFormValues = _ddmFormValuesFactory.create(actionRequest, ddmForm);

            try {
                serviceContext = ServiceContextFactory.getInstance(
                    DDMFormInstanceRecord.class.getName(), actionRequest);
            } catch (PortalException e) {
                e.printStackTrace();
            }
                        
            if(formInstanceRecordId > 0) {
                try {
                    DDMFormInstanceRecordLocalServiceUtil.updateFormInstanceRecord(serviceContext.getUserId(), formInstanceRecordId, Boolean.FALSE,
                            ddmFormValues, serviceContext);
                } catch (PortalException e) {
                    e.printStackTrace();
                }
            }else {
                try {
                    DDMFormInstanceRecordLocalServiceUtil.addFormInstanceRecord(serviceContext.getUserId(), serviceContext.getScopeGroupId(),
                            ddmFormInstance.getFormInstanceId(), ddmFormValues,
                            serviceContext);
                } catch (PortalException e) {
                    e.printStackTrace();
                }
            }
        }

Note - Once the Form is Save its reference Id ddmFormIntanceRecordId  can be used for future reference.

Blogs

thank you for this share Mohammed.  It was just the hint that we were looking for.   One item we are working toward is the support for auto-save.  Did you end up finding a way to make the form auto-save happen while using the custom portlet wrapper?