2

I have worked simple things with lightning components I am trying to make things more complex but with lockservices I see that everything is more difficult because I can not access the DOM

For example in angular 2 create a dynamic form based on fieldset in one day I want to migrate it to lightning but I see that it is complicated I already have part of the code

The problem is that with lightning: input I can not access the value of the fields and try in different ways but I can not access.

Example 1 aura:id

var val = "{! v.obj." + fi.name + "}";

["lightning:input", {"label": fi.label, "name": fi.name, "aura: id": val}]

When using expression the form is generated but something strange happens the input can not be edited is blocked

EXAMPLE 2 try to use class

var val = "fi.name"; arrayForm.push (["lightning:input", {"label": fi.label, "name": fi.name, "class": val}]);

lightning:input does not support add class I don't see in the DOM

EXAMPLE 3 getElementsByName

use document.getElementsByName ("City__c") to get the value. I get this error "Illegal invocation at NodeList.remoteFunction"

if I do it with ui or normal input text it works but it does not make sense because I have to add all the html and the slds.

helper

    getFieldSetHelper : function(component) {
    var action = component.get("c.getFieldSetApex");

    var objectName=component.get("v.objectName");
    var fieldSetName=component.get("v.fieldSetName");

    var spinner = component.find("mySpinner");
    $A.util.toggleClass(spinner, "slds-hide");

    action.setParams({ "objectName" : objectName,"fieldSetName":fieldSetName });

    action.setCallback(this, function(response) {
        var state = response.getState();
        if (component.isValid() && state === "SUCCESS") {
            var retValues=response.getReturnValue();
            console.log(retValues.obj);

            component.set("v.obj",retValues.obj);
            component.set("v.fieldsLst", retValues.fields);
            this.doInit(component);
        }
        $A.util.toggleClass(spinner, "slds-hide");
    });
    $A.enqueueAction(action);

},
close: function(component) {

},
save: function(component) {

    //var data = document.getElementsByName("City__c");
    //var data = document.querySelector("City__c");
    //var data = component.find("City__c");
    //var data = component.get("v.obj");
    console.log(data);

},
doInit : function(component) {

    var fieldsLst=component.get("v.fieldsLst");

    var obj=component.get("v.obj");

    var arrayForm=[];
    var objectName=component.get("v.objectName");

    for(var fi of fieldsLst){
        var val="{!v.obj."+fi.name+"}";
        var idy=objectName+"_"+fi.name;
        if(fi.type=='STRING'){

    //Here I try in different ways

            arrayForm.push(["lightning:input",{"label":fi.label,"name":fi.name,"class":idy}]);
        }
    }

    $A.createComponents(arrayForm,
                        function(components, status, errorMessage){
                            if (status === "SUCCESS") {
                                var body = component.get("v.body");
                                body.push(components);
                                component.set("v.body", components);
                                component.set("v.obj", components);

                            }
                            else if (status === "INCOMPLETE") {
                                console.log("No response from server or client is offline.")
                            }
                                else if (status === "ERROR") {
                                    console.log("Error: " + errorMessage);
                                }
                        }
                       );


}

    })

component

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" controller="FieldSetToForm">
<aura:handler name="init" value="{!this}" action="{!c.getFieldSetInit}" />
<aura:attribute name="objectName" type="string" default="Account"/>
<aura:attribute name="fieldSetName" type="string" default="accountFS"/>
<aura:attribute name="fieldsLst" type="FieldSetToForm.Inputx[]"/>

<aura:attribute name="obj" type="sobject"/>

<lightning:button variant="brand" label="Close" iconName="utility:download" iconPosition="left" onclick="{!c.close}" />
 <lightning:button variant="brand" label="Save" iconName="utility:download" iconPosition="left" onclick="{!c.save}" />

<input type="hidden" name="valuesData" value="" id="valuesData"/>
{!v.body}



<div class="holder">
    <lightning:spinner variant="brand" size="large" aura:id="mySpinner" alternativeText="..."/>
</div>

controller

({
getFieldSetInit : function(component, event, helper) {
    helper.getFieldSetHelper(component);        
},
close : function(component, event, helper) {
    helper.close(component);
},
save : function(component, event, helper) {
    helper.save(component);
}
})

I Love Angular

I feel that lightning is not mature but I want to use it ...

  • Lightning is mature, you're simply trying to apply Angular directly to Lightning, which is not how it works. You need to follow the rules, or you'll not get very far. – sfdcfox Sep 1 '17 at 3:36
6

In order to bind to something dynamically, you need a reference. Here is a very basic, no-frills, slightly buggy implementation that demonstrates that this basically works.

Notice how I use component.getReference to dynamically link to a field. Also notice how I can bind to the same field twice, which literally lets me modify the same field more than once in real-time, just to prove that they are real references.

With a little more error checking and fact-gathering, this could indeed be a dynamic form with some basic describe data, etc. Notice how I do not use aura:id at all. I simply bound all the fields to a common object, and I could get and retrieve the values at will (in this case, demonstrated through Object.keys). I could also bind this object to, say, a force:recordData to dynamically save the data back to the server, or send it through a server action in Apex.


<aura:application extends="force:slds">
    <aura:attribute name="accountRecord" type="Account" default="{ 'sobjectType': 'Account' }" />
    <aura:attribute name="edits" type="Aura.Component[]" />
    <aura:attribute name="fieldName" type="String" />
    <aura:attribute name="output" type="String" />

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

    {!v.output}

    <hr />

    {!v.edits}

    <ui:inputText value="{!v.fieldName}" />
    <ui:button press="{!c.addField}" label="Add" />
    <br/>
    <ui:button press="{!c.display}" label="Show Data" />
</aura:application>

({
    init: function(component, event, helper) {
        component.set("v.edits", []);
    },
    addField: function(component, event, helper) {
        var field = component.get("v.fieldName"), 
            obj = component.get("v.accountRecord");
        obj[field] = "";
        component.set("v.accountRecord", obj);
        $A.createComponent(
            "lightning:input", {
                value: component.getReference("v.accountRecord."+component.get("v.fieldName")),
                label: component.get("v.fieldName"),
                type: "Text"
            },
            $A.getCallback(function(newCmp, status, error) {
                var edits = component.get("v.edits");
                edits.push(newCmp);
                component.set("v.edits", edits);
            })
        );
    },
    display: function(component, event, helper) {
        var obj = component.get("v.accountRecord");
        var results = [];
        Object.keys(obj).forEach(function(key) { results.push(key+":"+obj[key])});
        component.set("v.output", results.join('\n'));
    }
})

Here's a demo of me dynamically binding stuff:

Dynamic Component Generation

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.