0

These problems have plagued me too much time. Maybe my implementation method is problematic. Is there a better way? Ask a friend to help me.

Question 1: When I get each row value in a dynamic table, if I define [aura:id="ParentField"], this won't work because aura:id is limited to one row.

Question 2: If I use labelClass="{!index}" to get the current row,

var getLabel = event.getSource().get('v.labelClass');

I will assign a value to the {!v.childList}, but if the table has multiple rows, all rows will have values. How to assign values only to rows of operations, not all rows?

Question 3: I have 2 ui:inputSelect needs to set the change method. When I add [labelClass="{!index}"] for the first [ui:inputSelect], the second one still needs to add [labelClass="{ !index}"], these 2 [labelClass="{!index}"] will affect each other and will not work.

This is my CMP file

<aura:component implements="flexipage:availableForAllPageTypes,force:appHostable" controller="AccountGroupController">
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />

    <aura:attribute name="PackTag" type="GroupLabel__c[]"/>
    <aura:attribute name="parentList" type="list" default="[]" description=""/>
    <aura:attribute name="childList" type="list" default="[]"/>
    <aura:attribute name="pickListMap" type="map"/>
    <aura:attribute name="disabledChildField" type="boolean" default="true"/>
    <aura:attribute name="objectName" type="string" default="GroupLabel__c"/>
    <aura:attribute name="parentFieldAPI" type="string" default="ParentPicklist__c"/>
    <aura:attribute name="childFieldAPI" type="string" default="ChildPicklist__c"/>
    <aura:attribute name="parentFieldLabel" type="string" />
    <aura:attribute name="childFieldLabel" type="string"/>
    <aura:attribute name="parentValue" type="string" default=""/>
    <aura:attribute name="childValue" type="string" default=""/>

    <div class="slds-box">
        <table class="slds-table slds-table_bordered slds-table_cell-buffer">
            <thead>
                <tr class="slds-text-title_caps">
                    <th scope="col">
                        <div class="slds-truncate">S.No</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Classify">Classify</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Field">Field</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Operator">Operator</div>
                    </th>
                    <th scope="col">
                        <div class="slds-truncate" title="Value">Value</div>
                    </th>
                </tr>
            </thead>
            <tbody>
                <aura:iteration items="{!v.PackTag}" var="item" indexVar="index">
                <tr class="slds-text-title_caps" id="{!index}">
                    <td>
                        {!index}
                    </td>
                    <td>
                        <ui:inputSelect value="{!item.ParentPicklist__c}" aura:id="ParentField" labelClass="{!index}" change="{!c.classifyChange}">
                            <aura:iteration items="{!v.parentList}" var="value">
                                <option value="{!value}">{!value}</option>
                            </aura:iteration>
                        </ui:inputSelect>
                    </td>
                    <td>
                        <ui:inputSelect value="{!item.ChildPicklist__c}" aura:id="childField" change="{!c.onSelectChange}">
                            <aura:iteration items="{!v.childList}" var="value">
                                <option value="{!value}">{!value}</option>
                            </aura:iteration>
                        </ui:inputSelect>
                    </td>
                    <td>
                        <ui:inputSelect>
                            <option value="null">-None-</option>
                            <option value="equal">equal</option>
                            <option value="not equal to">not equal to</option>
                            <option value="Less than">Less than</option>
                            <option value="greater or equal to">greater or equal to</option>
                        </ui:inputSelect>
                    </td>
                    <td>
                        {!v.body}
                    </td>
                    <td>
                        <!-- conditionally Display Add or Delete Icons if rowIndex is 0 then show Add New Row Icon else show delete Icon -->
                        <aura:if isTrue="{!index == 0}">
                            <a onclick="{!c.AddNewRow}">
                                <lightning:icon iconName="utility:add" class="slds-icon slds-icon_small" size="small" alternativeText="add"/>
                                <span class="slds-assistive-text">Add Icon</span>
                            </a>
                            <aura:set attribute="else">
                                <a onclick="{!c.removeRow}" id="{!index}">
                                    <lightning:icon variant="error" iconName="utility:delete" class="slds-icon slds-icon_small" size="small" alternativeText="icon"/>
                                    <span class="slds-assistive-text">Delete Icon</span>
                                </a>
                            </aura:set>
                        </aura:if>
                    </td>
                </tr>
                </aura:iteration>
            </tbody>
        </table>
    </div>
</aura:component>

This is my JS file

({
    doInit : function(component, event, helper) {

        var RowItemList = component.get("v.PackTag");
        RowItemList.push({
            'sobjectType': 'GroupLabel__c',
            'ParentPicklist__c':'',
            'FieldAPI__c': '',
            'Operator__c': '',
            'Input_Value__c': ''
        });

        component.set("v.PackTag", RowItemList);

        var action = component.get("c.getDependentPicklist");
        action.setParams({
            ObjectName : component.get("v.objectName"),
            parentField : component.get("v.parentFieldAPI"),
            childField : component.get("v.childFieldAPI")
        });

        action.setCallback(this, function(response){
            var status = response.getState();
            if(status === "SUCCESS"){
                var pickListResponse = response.getReturnValue();

                //save response 
                component.set("v.pickListMap",pickListResponse.pickListMap);
                component.set("v.parentFieldLabel",pickListResponse.parentFieldLabel);
                component.set("v.childFieldLabel",pickListResponse.childFieldLabel);

                // create a empty array for store parent picklist values 
                var parentkeys = []; // for store all map keys 
                var parentField = []; // for store parent picklist value to set on lightning:select. 

                // Iterate over map and store the key
                for (var pickKey in pickListResponse.pickListMap) {
                    parentkeys.push(pickKey);
                }

                //set the parent field value for lightning:select
                if (parentkeys != undefined && parentkeys.length > 0) {
                    parentField.push('-None-');
                }

                for (var i = 0; i < parentkeys.length; i++) {
                    parentField.push(parentkeys[i]);
                }  
                // set the parent picklist
                component.set("v.parentList", parentField);

            }
        });

        $A.enqueueAction(action);
    },

    AddNewRow : function(component, event, helper){
        var addRowInList = component.get("v.PackTag");
        var contactObj = new Object();
        addRowInList.push(contactObj);
        component.set("v.PackTag",addRowInList);
    },
    removeRow : function(component, event, helper){
        var whichOne = event.target.getAttribute("id")
        var AllRowsList = component.get("v.PackTag");
        AllRowsList.splice(whichOne, 1);
        component.set("v.PackTag", AllRowsList);
    },

    classifyChange : function(component, event, helper) {

        var controllerValue = component.find("parentField").get("v.value");
        var pickListMap = component.get("v.pickListMap");

        if (controllerValue != '-None-') {
             //get child picklist value
            var childValues = pickListMap[controllerValue];
            var childValueList = [];
            childValueList.push('-None-');
            for (var i = 0; i < childValues.length; i++) {
                childValueList.push(childValues[i]);
            }
            // set the child list
            component.set("v.childList", childValueList);

            if(childValues.length > 0){
                component.set("v.disabledChildField" , false);  
            }else{
                component.set("v.disabledChildField" , true); 
            }

        } else {
            component.set("v.childList", ['-None-']);
            component.set("v.disabledChildField" , true);
        }
    },

    onSelectChange : function(component, event, helper) {
        var selected = component.find("childField").get("v.value");
        console.log('get = ' + selected);

        if (selected === 'Child Option 1') {
            component.set("v.body",[]);
            $A.createComponent(
                "ui:inputText",
                {
                    "placeholder":"Enter Child Option 1",
                    "class": "slds-input"
                },
                function(newInp, status, errorMessage){
                    if (status === "SUCCESS") {
                        var body = component.get("v.body");
                        body.push(newInp);
                        component.set("v.body", body);
                    }
                }
            );
        }else{
            component.set("v.body",[]);
        }
    }
})

This is the result I want to achieve: If [CLASSIFY] selects option 1, [FIELD] only [child option 1] can be selected. [VALUE] will also change, such as data input, select input, input box, etc. enter image description here

enter image description here

I have completed the single line feature, but if it is multiple lines, these features will not be available.

  • For your question 1: you can use data attributes to store the parentfield information. data-parentfield="ParentField" Then you can access it in your controller via event.curentTarget.getAttribute('data-parentfield'); – JRiffe Oct 18 '19 at 16:30
  • You can also use the data attributes to set the row index as well. data-rowIndex="{!index} – JRiffe Oct 18 '19 at 16:31
1

you have to take current row Item and then Update it then rebind to PackTag list with same Place by index, i just use Classify and field columns in below code snippet. and in your AddNewRow function, you pushing normal JSobject it shouldn't , you need to push 'sobjectType': 'GroupLabel__c' type let me know if you find any issue.

cmp

<aura:component controller="SeTesting" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,forceCommunity:availableForAllPageTypes" 
        access="global" >
<aura:attribute name="pickListMap" type="map" default="{'Option1':['Child Option1','Grand Child option1'],'Option2':['Child Option1','Grand Child option1','Grand Child option2']}"/>
<aura:attribute name="parentList" type="list" default="['Option1','Option2']" />
<aura:attribute name="childList" type="list" default=""/>
 <aura:attribute name="PackTag" type="List"/>

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

<div class="slds-box">
    <table class="slds-table slds-table_bordered slds-table_cell-buffer">
        <thead>
            <tr class="slds-text-title_caps">
                <th scope="col">
                    <div class="slds-truncate">S.No</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="Classify">Classify</div>
                </th>
                <th scope="col">
                    <div class="slds-truncate" title="Field">Field</div>
                </th>                    
            </tr>
        </thead>
        <tbody>               
                <aura:iteration items="{!v.PackTag}" var="item" indexVar="index">
                    <tr class="slds-text-title_caps" id="{!index}">
                        <td>
                            {!index}
                        </td>
                        <td>
                            <lightning:select aura:id="select"  name="{!index}" Class="slds-col slds-size_1-of-2 slds-p-horizontal_x-small" onchange="{! c.classifyChange }" value="{!item.ParentPicklist__c}">
                                <option value="-None-">-None-</option>
                                <aura:iteration items="{!v.parentList}" var="value">
                                    <option value="{!value}">{!value}</option>
                                </aura:iteration>
                            </lightning:select>
                        </td>
                        <td>
                            <lightning:select aura:id="select"  name="{!index}" Class="slds-col slds-size_1-of-2 slds-p-horizontal_x-small" onchange="{! c.onSelectChange }" value="{!item.ChildPicklist__c}">
                                <option value="-None-">-None-</option>
                                <aura:iteration items="{!v.childList}" var="value">
                                    <option value="{!value}">{!value}</option>
                                </aura:iteration>
                            </lightning:select>
                        </td>
                        <td>
                            {!v.body}
                        </td>
                        <td>
                            <!-- conditionally Display Add or Delete Icons if rowIndex is 0 then show Add New Row Icon else show delete Icon -->
                            <aura:if isTrue="{!index == 0}">
                                <a onclick="{!c.AddNewRow}">
                                    <lightning:icon iconName="utility:add" class="slds-icon slds-icon_small" size="small" alternativeText="add"/>
                                    <span class="slds-assistive-text">Add Icon</span>
                                </a>
                                <aura:set attribute="else">
                                    <a onclick="{!c.removeRow}" id="{!index}">
                                        <lightning:icon variant="error" iconName="utility:delete" class="slds-icon slds-icon_small" size="small" alternativeText="icon"/>
                                        <span class="slds-assistive-text">Delete Icon</span>
                                    </a>
                                </aura:set>
                            </aura:if>
                        </td>
                    </tr>
                </aura:iteration>

        </tbody>
    </table>
</div>
<div>
    <aura:iteration items="{!v.PackTag}" var="item" indexVar="index">
        {!item.ParentPicklist__c} --- {!item.ChildPicklist__c}
    </aura:iteration>
</div>

cmpController

({
doInit: function (component,event,helper) {       
  helper.AddgetnewObject(component);
},
AddNewRow : function(component, event, helper){
     helper.AddgetnewObject(component);
    //['Child Option1','Grand Child option1','Grand Child option2']
},
classifyChange : function(component, event, helper) {
     var pickListMap = component.get("v.pickListMap"),
         index = event.getSource().get("v.name"),
         RowItemList = component.get("v.PackTag"),
         currentrow = RowItemList[index],
         controllerValue = event.getSource().get("v.value");
    if (controllerValue != '-None-') {
         //get child picklist value
        var childValues = pickListMap[controllerValue];
        var childValueList = [];
        childValueList.push('-None-');
        for (var i = 0; i < childValues.length; i++) {
            childValueList.push(childValues[i]);
        }
        // set the child list
        currentrow.childList = childValueList;
        //component.set("v.childList", childValueList); 


    } else {
       currentrow.childList = ['-None-'];
        //component.set("v.childList", ['-None-']);

    }
    currentrow.ParentPicklist__c = controllerValue;
    RowItemList.splice(index, 1, currentrow);
    component.set("v.PackTag",RowItemList);
},
 onSelectChange : function(component, event, helper) {
     var index = event.getSource().get("v.name"),
         RowItemList = component.get("v.PackTag"),
         currentrow = RowItemList[index],
         selected = event.getSource().get("v.value");
     if(selected !== '-None-'){
         currentrow.ChildPicklist__c = selected;
         RowItemList.splice(index, 1, currentrow);
         component.set("v.PackTag",RowItemList);
     }
}

})

cmphelper

({
AddgetnewObject : function(component){
     var RowItemList = component.get("v.PackTag");
    RowItemList.push({
        'sobjectType': 'GroupLabel__c',
        'ParentPicklist__c':'',
        'ChildPicklist__c': ''
    });
    component.set("v.PackTag", RowItemList);
}
})
  • Hi @sdandamud1 Thank you very much for the answer, which is very useful to me.But when I implemented it according to your ideas, I still encountered two problems. Question 1: When setting the [childList] value, if the table has multiple rows, [childList] will overwrite all rows, not the current row. – Ou Zhang Oct 21 '19 at 8:56
  • Question 2: When I dynamically create {!v.body}, the created component will also be displayed in all rows instead of the current row. There is also no way for the dynamically created component of {!v.body} to save the input value. I believe that I still need an index to solve my two problems, but I have no way, can you help me? – Ou Zhang Oct 21 '19 at 8:56
  • for Question 1: i just update the answer with add a childList Property for current row Item for UI dynamic mechanism but you need to remove this childList property from each item if you make any server calls because there is no childList field on GroupLabel__c object. For Question you instead of dynamic component i would suggest go with Boolean values to show/hide the lighnting:input component. – sdandamud1 Oct 21 '19 at 16:16
  • Hi @sdandamud1 After my efforts, I used { lightning:recordEditForm } to solve the first problem. But creating components dynamically for each row and getting input values is still unresolved. Do you have any good ideas? Heartfelt thanks – Ou Zhang Oct 22 '19 at 10:26
  • Fortunately, I found your conversation with Apple and used [Lex expressions] to complete the second question. Thank you very much and wish you a happy life! – Ou Zhang Oct 23 '19 at 7:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.