4

I'm creating components from a fieldset, which means determining that a field in the set is a picklist in real time, then creating that inputSelect dynamically, and then creating the inputSelectOptions.

Here's the component:

<aura:component controller="ltngController"
            implements="forceCommunity:availableForAllPageTypes">
<aura:attribute name="userId" type="String" />
<aura:attribute name="contact" type="Contact"/>
<aura:attribute name="fieldSetName" type="String"/>
<aura:attribute name="fields" type="Object[]"/>
<aura:attribute name="picklistValues" type="Object[]" />    

<aura:attribute name="form" type="Aura.Component[]"/>
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<!--HTML and other Lightning components-->
<div class="row">
    <div class="section">
        <div class="cell form">
                  {!v.form}   
        </div>
    </div>
</div></aura:component>

The JSController runs the doInit which calls the server and gets the fieldSet data. This data is moved into a custom FieldSetMember class whose properties are AuraEnabled. For picklists, a describe call gets the Picklist value for this field and stores them in a list of custom PicklistValues objects. Checking the Debug Log and the Chrome Inspector verifies that all the data is available in the component controller, so that's not the problem.

Next step is to dynamcially create the components to hold the fieldSetdata in a helper method called 'createForm'. When a picklist value is encountered, I run the following :

createForm2 : function(cmp) {
    var fieldPicklistMap = cmp.get("v.fieldPicklistMap");
    var fields = cmp.get('v.fields');
    var obj = cmp.get('v.contact');
    var comps = [];
    for (var i = 0; i < fields.length; i++) {
        var field = fields[i];
        var labl = field.label;

        if (field.type != 'PICKLIST'){// non-picklist fields (these are appearing)
            var config = this.configMap[field.type.toLowerCase()]; // gets non-picklist field component definitions and attributes
            if (config){
                config.attributes.label = field.label;
                config.attributes.required = field.required;
                config.attributes.value = obj[field.fieldPath];
                config.attributes.fieldPath = field.fieldPath;
                comps.push([config.componentDef,config.attributes]);
            }
        } else {                // inputSelect and selectOption components
            var picklistItems = fieldPicklistMap.get(field.label); // this field's picklist values from the map
            var fieldPath = '{!v.contact.'+field.fieldPath+'}';
            comps.push(["ui:inputSelect",
                        {"aura:id":field.label,"label":field.label,"required":field.required,"value":fieldPath}]);
            for (var j = 0; j < picklistItems.length; j++){
                var pItem = picklistItems[j];
                comps.push(["ui:inputSelectOption",
                                  {"label" : "test",//pItem,
                                   "text" : "test",//pItem,
                                   "name" : pItem}]);
            }
        }
    }
    $A.createComponents(comps,
        function(components,status,errorMessage){
            var form = cmp.get("v.form");
            if (status === "SUCCESS"){
                for (var i = 0; i < components.length; i++){
                    var com = components[i];
                    field = fields[i];
                    var comLabel = com.get("v.label");
                     debugger;
                    if (fieldPicklistMap.get(comLabel) == null){
                        form.push(com);
                    } else {
                        var items = fieldPicklistMap.get(comLabel);
                         debugger;
                        var iL = items.length;
                         debugger;
                        var options = com.get("v.options");
                        for (var k = 0; k < iL; k++){
                            i++;
                            var optCom = components[i];
                            var body = optCom.get("v.body");
                            var optComValue = optCom.get("v.text");
                            optCom.set("v.body",body);
                            options.push(optCom);
                        }
                        com.set("v.options",options);
                        form.push(com);
                    }
                }
                cmp.set("v.form",form);
                 debugger;
            } else {
                var error = errorMessage;
                 debugger;
            }
        }
    );
     debugger;
}

debugger lines ad other code to verify the inputSelect and selectOptions show that all of these are being created and added into the inputSelect and form components in the page. However, when I run the process, the picklist fields appear, with the correct label, but the drop-down for each reveals no selectOptions, even though there is enough empty space in the dropdown to match the number of options that should be visible. Here is a screen shot of the rendered page: enter image description here Note that the Gender dropdown has the right number of lines, but no selectOption data.

Looking at the HTML for this component shows the following:

Here is the HTML for the Gender inputSelect component. The options are coming up as undefined!!

<div data-aura-rendered-by="442:0" class="uiInput uiInputSelect uiInput--default uiInput--select" data-aura-class="uiInput uiInputSelect uiInput--default uiInput--select">
<label class="uiLabel-left form-element__label uiLabel" for="9:114;a" data-aura-rendered-by="437:0" data-aura-class="uiLabel">
    <span class="" data-aura-rendered-by="438:0">Gender</span>
    <!--render facet: 440:0-->
    <!--render facet: 441:0-->
</label>
<select class=" select" size="1" aria-describedby="" id="9:114;a" data-aura-rendered-by="14:114;a" data-interactive-lib-uid="4">
    <!--render facet: 15:114;a-->
    <option label="" value="undefined"></option>
    <option label="" value="undefined"></option>
</select>

This seems like it should be a fairly simple process of componet creation, and I'm doing everything right as far as the javascript inspector is telling me. What do you experts think I'm doing wrog and how might I get these fields to render correctly??

  • have you verified the content of the attribute picklistValues? Can you set it to a constant object so that your code is fully self contained? – Uwe Heim Oct 21 '17 at 8:36
  • I have verified that the picklistValues content is available in the code. The debugger confirms that each selectOption is getting data from the picklistvalues as they are generated. I can also verify that I can pull then back into the controller after they have been inserted into the inputSelect options and the inputSelect has been added to the form. Not sure what you mean by setting it to a constant object in this case... – VeMan Oct 21 '17 at 19:29
  • given just your code, I can't be sure that pItem.ItemLabel is not an empty string. you should populate picklistValues in the code you provide here, so that people who want to help can repro it. best would be by assign somthing to it. – Uwe Heim Oct 22 '17 at 7:51
  • I have been able to verify that the picklistValues are there in the debugger when running the createForm method. I've also verified that the values in the inputSelectOptions values are also there when accessing them after the components have been created. Components are created, the values are verified in the debugger, the select fields appear, the correct number of selectOption lines appear but the selectOption values do not. Where between the assignment of the values to the selectOption components, and the loading of the page with those created components do the option values get lost?? – VeMan Oct 22 '17 at 20:18
  • I've updated the createForm method. Now, all the components are instantiated and added to a comps list so that all components can be created at the same time. Someone suggested that having separate createcomponent calls in a for loop might have issues given that its an asynchronous process. So now ther is just one call and all components are managed in the callback methodafter all have been created. I've also hard-coded the selectOption values to remove any doubts about whether the picklistValues list is loaded. I'm still getting empty selectOption lines. – VeMan Oct 22 '17 at 22:19

Your Answer

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

Browse other questions tagged or ask your own question.