• Karla Martinez3
  • NEWBIE
  • 0 Points
  • Member since 2018

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 1
    Questions
  • 1
    Replies
Hello everyone! I'm a Jr working with Lightning Components, and I have a problem, I read all the possible documentation related to lightning:recordEditForm but I didn't have success with the issue that I have. 

I'm trying to create a Dynamic Form with two LC one is WorkOrder (parent) and the other one is WorkOrderLineItem (child) I define the FieldSets API Name via the Design Resource, and also in my form I have an Add Button for add WorkOrderLineItems as many I want into my Parent Form, and I placed one independet Submit button for save all the records in the corresponding objects. The thing is, when I'm trying to save the form with all the fields filled, I don't receive any errors, but when I go to WorkOrder records I can see one new record created with or without WorkOrderLineItems  BUT with Empty fields. E.g:  I created one WorkOrder with one WorkOrderLineItem, when I look into WorkOrder Records I can see the new record but without the information that I filled before, but with the WorkOrderLineItem. 

I'm using on both components the Lightning:recordEditForm, I wanna know if is one issue with this specific component when has a child or I can't do thie Dynamic Form in this way or if is another thing that I don't know... Can you guys help me to understand? 

Thanks!!!

Below my code:
  1. PARENT CMP <!--ComplexWOForm.cmp-->
<aura:component controller="FSFormController"                			
                implements="flexipage:availableForRecordHome,force:hasRecordId,force:hasSObjectName,flexipage:availableForAllPageTypes">
    
    <aura:attribute name="recordTypeId" type="String" />   
    <aura:attribute name="fields" type="Object[]" access="private" />
    
    
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    <!-- <aura:handler event="force:refreshView" action="{!c.init}" /> -->
    
    
    <aura:attribute name="fieldSetName" type="String" description="The api name of the field set to use from the given object." />
    <aura:attribute name="fieldSetName2" type="String" description="The api name of the field set to use from the given object." />
    <aura:attribute name="WOLIDetailsList" type="List" default="[]"/>
    <aura:attribute name="sObjectName2" type="string" />
    <aura:attribute name="object2" type="WorkOrderLineItem" default="{'sobjectType':'WorkOrderLineItem','WorkOrderId':''}" />
     <aura:attribute name="mrName"  type="string"  description="API name of MR field on the child. "/>
    <aura:attribute name="object1" type="WorkOrder" default="{'sobjectType':'WorkOrder'}" />
    
    
    <!--the following attribute is for receive the ID of the parent
  I use it in the controller on de doSubmit-->
    <aura:attribute name="ParentRecordId" type="String" />
    
    
    <!--FORM start here-->
    
    <lightning:recordEditForm aura:id="test"
                              objectApiName="{! v.sObjectName }"
                              recordId="{! v.recordId }"
                                                           >
        <lightning:messages />
        
        <!-- Header -->   
        
        <div class=" slds-size_6-of-8 slds-box slds-theme_default ">
            <div class="slds-page-header slds-grid slds-grid_pull-padded-medium">
                
                <div class="slds-order_1">
                    <div class="slds-col slds-p-horizontal_medium"> 
                        <img src="{!$Resource.twiloLogo}"/> 
                    </div>
                </div>
                
                <div class="slds-order_2">
                    <div class="slds-col slds-p-horizontal_medium">
                        <div class="slds-text-heading_large"> 
                            <h1 > Complex Work Order.</h1>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        
        <!-- /Header -->
        
        
        <!-- Creating the Parent Form--> 
        <div class="slds-size_6-of-8 slds-box slds-theme_default">
            <aura:iteration items="{!v.fields}" var="field" indexVar="indexParent">
                <lightning:inputField aura:id="{!'fieldId' + indexParent}" 
                                      fieldName="{! field.APIName }" 
                                      class=" slds-p-top_small slds-m-top_medium" />
            </aura:iteration>
        </div>
        
        <!--/ Creating the Parent Form-->  
        
        <!-- Adding WOLI List to Parent Form-->
        
        <aura:iteration items="{!v.WOLIDetailsList}" var="item" indexVar="index">
            <div class="slds-size_6-of-8 slds-box slds-theme_default">
                <!--Dynamic Binding -->
                <span class="slds-col slds-p-horizontal_medium">
                    <c:Add_WOLI fieldSetName2="{!v.fieldSetName2}" 
                                sObjectName2="{!v.sObjectName2}" 
                                RecordIdChild="{!v.ParentRecordId}" 
                                WOLIDetailsInnerComponent="{!v.WOLIDetailsList}" 
                                indexNo="{!index}"/>
                    <hr/>
                </span>
            </div>
        </aura:iteration>
        
        
        <div>
            <lightning:button iconName="utility:add" variant="border-filled" label="WOLI" onclick="{!c.addDetails}"/>          
        </div> 
        
       
        <!-- /Adding WOLI List to Parent Form-->
        
       
          
    
    </lightning:recordEditForm>
     <lightning:layout horizontalAlign="center" class="slds-m-top_large">                    
            <lightning:button variant="brand" label="Submit" title="Submit" type="submit" onclick="{!c.handleSubmit}"/>
            <lightning:button variant="neutral" label="Cancel" title="Cancel" type="text" onclick="{!c.handleCancel}"/>
        </lightning:layout> 
</aura:component>
 2. <!--ComplexWOFormController.js-->
({
    init: function(cmp, event, helper) {
        
        var fieldSetName = cmp.get('v.fieldSetName');
        var sobjectName = cmp.get('v.sObjectName');
        var recordId = cmp.get('v.recordId');
        
        console.log("IM @ init parent fieldsetname ",fieldSetName);
        console.log("IM @ init parent sobjectName",sobjectName);
        console.log("IM @ init parent  recordId",recordId);
        
        if (!fieldSetName) {
            console.log('The field set is required.');
            return;
        }
        
        var getFormAction = cmp.get('c.getForm');
        
        getFormAction.setParams({
            fieldSetName: fieldSetName,
            objectName: sobjectName,
            recordId: recordId
        });
        
        getFormAction.setCallback(this, function(response) {
            var state = response.getState();
            
            console.log('FieldSetFormController getFormAction callback PARENT');
            console.log("callback state: " + state);
            
            if (cmp.isValid() && state === "SUCCESS") {
                var form = response.getReturnValue();
                cmp.set('v.fields', form.Fields);
            }
        }
                                 );
        $A.enqueueAction(getFormAction);
    },
    
    handleSubmit : function(component, event, helper) {
        
        console.log("I'm at Handle Submit " );
        
        
        
        var simpleWO =component.get("v.object1");
        
        var action= component.get("c.saveSimpleWO");
        
        action.setParams({simpleWO :simpleWO});
        
        action.setCallback(this, function(response) {
            var state = response.getState();
            
            console.log("State of SIMPLE WO",state);
            
            if (state === "SUCCESS") {
                
                
                // Alert the user with the value returned 
                // from the server
                alert("From server: " + response.getReturnValue());
                
                var parentId= response.getReturnValue();
                
                //assign the value of parent ID to our attribute
                component.set("v.ParentRecordId",parentId);
                
                
                // You would typically fire a event here to trigger 
                // client-side notification that the server-side 
                // action is compvare
                // 
                // add more logic her
                // store/save education detail records as well
                
                
                // component.find('test').submit();
                
            }
            else if (state === "INCOMPLETE") {
                // do something
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                        errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });//$A.enqueueAction adds the server-side action to the queue
        
        $A.enqueueAction(action);
        
    },
    
    handleCancel : function(component, event, helper) {
        
        event.preventDefault();
        helper.cancel(component,event);
    },
    
    addDetails: function(component,event,helper){
        
        console.log("Add WOLI Details");
        var CurrentWOLIdetailsList = component.get("v.WOLIDetailsList");
        
        
        var currentSize= parseInt(CurrentWOLIdetailsList.length);
        var NewSize= parseInt((currentSize)+1);
        
        
        CurrentWOLIdetailsList.push(NewSize);
        component.set("v.WOLIDetailsList", CurrentWOLIdetailsList);
        
    },
    
    
})

3. <!--ComplexWOFormHelper.js-->
({
	 cancel :function(cmp, event) {
        
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "title": "Cancel!",
            "message": "Record Not Saved"
        });
        toastEvent.fire();
        $A.get('e.force:refreshView').fire();
    },
})

4. <!--ComplexWOForm.design-->
<design:component>
    <design:attribute name="fieldSetName" label="Field Set Name for Parent Component (WorkOrder)" description="API valid Name of the field set to use." />
    <design:attribute name="fieldSetName2" label="Field Set Name for Child Component (WorkOrderLineItems)" description="API Name of the field set to use." />
    <design:attribute name="sObjectName" label="Object Name for Parent Component" description="API Name of the Object to use. This only needs to be populated when not on a record detail page." />
    <design:attribute name="sObjectName2" label="Object Name for Child Component" description="API Name of the Object to use. This only needs to be populated when not on a record detail page." />
    <design:attribute name="mrName" label="API name of MR field on the child. "/>
</design:component>
5. Child Component <!-- Add_WOLI.cmp -->
 
<aura:component controller="FSFormController"   
                implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    
    
    <!-- WOLI Object-->
    
    <aura:attribute name="fieldSetName2" type="String" description="The api name of the field set to use from the given object." />
    <aura:attribute name="sObjectName2" type="String" />   
    <aura:attribute name="object2" type="WorkOrderLineItem" default="{'sobjectType':'WorkOrderLineItem','WorkOrderId':''}" />
    
    <aura:attribute name="mrName" type="string" description="API name of MR field on the child. "/>
    
    <aura:attribute name="indexNo" type="Integer"/>
    <aura:attribute name="sequenceNo" type="Integer"/>
    
    <!--in EDU details is name="RegistrationRecordIdChild"-->
    <aura:attribute name="RecordIdChild" type="String"/>
    
    <!--this is the conection between the parent (I declared use this attribute on the parent COMPLEXWOFORM)-->
    <aura:attribute name="WOLIDetailsInnerComponent" type="List" />
    
    
    <aura:attribute name="fields2" type="Object[]" access="private" />
    
    
    <aura:handler name="init" value="{!this}" action="{!c.doinit}"/>
    
    <!-- <aura:handler event="force:refreshView" action="{!c.doinit}" />  -->
    
    <!---whenever any change occurs in RecordIdChild aura handler calls to the controller-->
    
    <aura:handler name="change" value="{!v.RecordIdChild}" action="{!c.saveWOLI}"/>
    
    <aura:handler name="change" value="{!v.indexNo}" action="{!c.changeInIndexNo}" />
    
    
    
    <div class="slds-size_6-of-8 slds-box slds-theme_shade">
        <div class="slds-page-header">
            <div class="sslds-col slds-p-horizontal_medium">
                <div class="slds-text-heading--small">
                    
                    <h2> WOLI # {!v.sequenceNo} </h2> 
                </div> 
            </div>
        </div>
    </div>
    
    
    <div class="slds-size_6-of-8 slds-box slds-theme_shade">
        
        <aura:iteration items="{!v.fields2}" var="field" indexVar="listIndex">
            
            <lightning:inputField aura:id="{!'fieldId' + listIndex}" 
                                  fieldName="{!field.APIName }" 
                                  required="{!field.DBRequired}" 
                                  type="{!field.Type}"
                                  class=" slds-p-top_small slds-m-top_medium" />
        </aura:iteration>
        
    </div>
    
    <lightning:button iconName="utility:delete" variant="border-filled" label="Delete this wOLI" onclick="{!c.deleteDetails}"/>
    
    
</aura:component>

6.  <!-- Add_WOLIController.js -->
 
({
    
    doinit: function(cmp, event, helper){
        var fieldSetName = cmp.get('v.fieldSetName2');
        var sobjectName = cmp.get('v.sObjectName2');
        var recordId = cmp.get('v.recordId');
        
        console.log("IM AT dointchild fieldsetname WOLI",fieldSetName);
        console.log("IM AT dointchild WOLI sobjectName",sobjectName);
        console.log("IM AT dointchild WOLI recordId",recordId);
        
        if (!fieldSetName) {
            console.log('The field set is required.');
            return;
        }
        console.log("DO INIT CHILD CMP")
        var getFormAction = cmp.get('c.getForm');
        
        getFormAction.setParams({
            fieldSetName: fieldSetName,
            objectName: sobjectName,
            recordId: recordId
        });
        
        getFormAction.setCallback(this, function(response){
            var state = response.getState();
            console.log('FSFormController getFormAction callback CHILD');
            console.log("callback state: " + state);
            
            if (cmp.isValid() && state === "SUCCESS") {
                console.log("Im at doinit child IS VALID ");
                var form = response.getReturnValue();
                cmp.set('v.fields2', form.Fields);
               }
        });
        $A.enqueueAction(getFormAction);
        helper.helperRectifySequence(cmp,event);
    },
    
    
    
    changeInIndexNo: function(component, event, helper){
                helper.helperRectifySequence(component,event);
            },
    
    
    deleteDetails : function(component, event, helper) {
        
        var NewWOLIdetails= component.get("v.WOLIDetailsInnerComponent");
        var currentIndex= component.get("v.indexNo");
        if(currentIndex > -1)
            NewWOLIdetails.splice(currentIndex,1);
        component.set("v.WOLIDetailsInnerComponent", NewWOLIdetails);
    },
    
    
    saveWOLI: function(component,event, helper){
        // call apex class function w the name of the class
        //SaveEducationalDetails        
        console.log("IM AT save WOLI");
        
        var RecordIdChild = component.get("v.RecordIdChild");
            component.set("v.object2.WorkOrderId",RecordIdChild);
	
        var sOName2 = component.get("v.object2");
        var rela= component.get("v.object2.WorkOrderId");
        
        
        var action = component.get("c.saveComplexWO");
        action.setParams({complexWO : sOName2});
        
        action.setCallback(this,function(response) {
            var state = response.getState();
            console.log("STATE @ SAVEWOLI: ",state);
            
            if (state === "SUCCESS") {
                console.log("Add WOLI saved");
                var toastEvent = $A.get("e.force:showToast");
                toastEvent.setParams({"title": "Success!",
                                      "message": "The Complex WO has been saved.",
                                      "type": "Success"});
                toastEvent.fire();
                $A.get('e.force:refreshView').fire();
            }
            else if (state === "INCOMPLETE") {
                // do something
            }
                else if (state === "ERROR") {
                    var errors = response.getError();
                    if (errors) {
                        if (errors[0] && errors[0].message) {
                            console.log("Error message: " + 
                                        errors[0].message);
                        }
                    } else {
                        console.log("Unknown error");
                    }
                }
        });//$A.enqueueAction adds the server-side action to the queue
        
        $A.enqueueAction(action);
        
    },
    
    
})

7. <!-- Add_WOLIHelper.js-->
({
	helperRectifySequence : function(component,event) {
        
        var indexNo= component.get("v.indexNo");
        var New=parseInt(indexNo)+1;
        component.set("v.sequenceNo",New);
		
	},
    
})

8. <!-- FSFormController.apxc-->
public with sharing class  FSFormController {


    @AuraEnabled
    public static FieldSetForm getForm(Id recordId, String objectName, String fieldSetName) {
        FieldSetForm form = new FieldSetForm();        
        form.Fields = getFields(recordId, objectName, fieldSetName);
        return form;
    }
    
    private static List<Field> getFields(Id recordId, String objectName, String fieldSetName) {
        Schema.SObjectType objectType = null;
        
        if (recordId != null) {
            objectType = recordId.getSobjectType();
        }
        else if (String.isNotBlank(objectName)) {
            objectType = Schema.getGlobalDescribe().get(objectName);
        }
        
        Schema.DescribeSObjectResult objectDescribe = objectType.getDescribe();
    
        Map<String, Schema.FieldSet> fieldSetMap = objectDescribe.fieldSets.getMap();
        
        Schema.FieldSet fieldSet = fieldSetMap.get(fieldSetName);
        
        List<Schema.FieldSetMember> fieldSetMembers = fieldSet.getFields();

        List<Field> fields = new List<Field>();
        for (Schema.FieldSetMember fsm : fieldSetMembers) {
            Field f = new Field(fsm);

            fields.add(f);
        }

        return fields;
    }
    
    public class FieldSetForm {
        @AuraEnabled
        public List<Field> Fields { get; set; }

        public FieldSetForm() {
            Fields = new List<Field>();
        }
    }
    
    
    @AuraEnabled
    public static id saveSimpleWO(SObject simpleWO){
            //DML op to save SWO
            insert simpleWO;
            return simpleWO.id;
    }
    
    
    
    @AuraEnabled
    public static id saveComplexWO(SObject complexWO){
         
        //DML op to save SWO
        insert complexWO;
        return complexWO.id;
    }   
    
}

9. <!-- Field.apxc -->
public class Field {

    public Field(Schema.FieldSetMember f) {
        this.DBRequired = f.DBRequired;
        this.APIName = f.fieldPath;
        this.Label = f.label;
        this.Required = f.required;
        this.Type = String.valueOf(f.getType());
    }
    
    public Field(Boolean DBRequired) {
        this.DBRequired = DBRequired;
    }
    
    @AuraEnabled
    public Boolean DBRequired { get;set; }
    
    @AuraEnabled
    public String APIName { get;set; }
    
    @AuraEnabled
    public String Label { get;set; }
    
    @AuraEnabled
    public Boolean Required { get;set; }
    
    @AuraEnabled
    public String Type { get; set; }
}


 
User-added image

I have created a permission set with the system permission "Two-Factor Authentication for User Interface Logins" and assigned it to the Samantha Cordero users. Here is the login history which i have used the Authenticator to authenticate the login of the user.

User-added image
What else am i missing? Any help is much appreciated.