1

so I have this component called "Tag" nested inside another component called "TagSelect".

After some user action, Tag raises an event, handled by TagSelect, which then executes an action.

The event is well raised by Tag, well handled by TagSelect, bu then the action is enqueued, but never executed.

The action is supposed to call some apex code to remove a record from the database.

TagRemoveEvent :

<aura:event type="COMPONENT" description="Fired when removing a Tag">
    <aura:attribute name="tagId" type="String" required="true" />
    <aura:attribute name="tagRecordId" type="String" required="true" />
</aura:event>

Tag :

    <aura:attribute name="tagName" type="String" required="true" />
    <aura:attribute name="tagId" type="String" required="true" />
    <aura:attribute name="tagRecordId" type="String" required="true" />

    <aura:registerEvent name="TagRemoveEvent" type="c:TagRemoveEvent" />

    <span class="slds-pill" style="margin-top: 5px; color: #0070d2;">
        <a onclick="{!c.removeMe}">x</a>&nbsp;
        {!v.tagName}
    </span>

</aura:component>

TagController :

({
    removeMe : function(component, event, helper) {
        console.log('fired! 1'); // displayed in console

        var cmpEvent = component.getEvent('TagRemoveEvent');
        cmpEvent.setParams({
            tagRecordId: component.get('v.tagRecordId'),
            tagId: component.get('v.tagId')
        });
        cmpEvent.fire();
    }
})

TagSelect :

<aura:component implements="flexipage:availableForAllPageTypes,force:hasRecordId,force:recordTab" controller="TagSelectController">


    <ltng:require styles="/resource/SLDS105/assets/styles/salesforce-lightning-design-system-ltng.css,/resource/JQueryUICSS"
                  scripts="/resource/JQueryJS,/resource/JQueryUIJS"
                  afterScriptsLoaded="{!c.doInit}" />

    <aura:attribute name="bRender" type="Boolean" default="false" />
    <aura:attribute name="tags" type="Tag[]" />

    <aura:handler name="TagRemoveEvent" event="c:TagRemoveEvent" action="{!c.removeTag}" />

// some code

    <aura:iteration items="{!v.tags}" var="tag">
            <c:Tag tagName="{!tag.tagName}" tagId="{!tag.tagId}" tagRecordId="{!tag.tagRecordId}" />
    </aura:iteration> 

// some code

    </aura:component>

TagSelectController :

({
    doInit : function(component, event, helper) {
        /* some code */
    },

    removeTag : function(component, event, helper) {
        console.log('fired! 2'); // displayed in console

        var parentId = event.getParam("tagRecordId");
        var tagId = event.getParam("tagId");

        helper.doRemove(component, parentId, tagId);
    }
})

TagSelectHelper :

({
    doRemove : function(component, parentId, tagId) {
        console.log('helper'); // never displayed in console

        var action = component.get("c.removeTag");

        action.setParams({
            parentId: parentId,
            tagId: tagId
        });

        action.setCallback(this, function(a) {

            var result = a.getReturnValue();
            console.log(result);

            if(result == null) {
                var tags = component.get('v.tags');
                var idx = 0;
                for(var i = 0; i < tags.length; i++) {
                    if(tags[i].tagId == tagId && tags[i].tagRecordId == parentId) {
                        tags.splice(i, 1);
                        break;
                    }
                }
                component.set('v.tags', tags);
            }
        });

        $A.enqueueAction(action); // never called, nothing happens, and no debug logs are generated
    }
})

I can't find what I did wrong.

I tried to put the helper code into a $A.getCallback but no luck (maybe I've been mistaken in the syntax ?)

Does someone understand what's happening ?

Thank you very much !

2 Answers 2

11

Okkaaaaay evreyone, I did it.

So first I moved my code from helper to controller. Then I noticed something strange (that I forgot to mention in the first place) : in the console, "fired 2!" was logged 2 times...

That was because the Apex method's name was the same of the Javascript controller method's one. So when executing var action = component.get("c.removeTag"); it kind of created a conflict, and the Javascript method was called twice, but the apex was never called !

So know it : a Javascript method name in a component controller can never be the same name in an Apex Lightning Controller !

Something I never noticed in the Lightning documentation (I may have missed it)...

1

Well, finding some info about this "bug", i noticed that i fall in the same error you do. I feel so stupid.

However, i can explain this behaviour, is not explicitly explained in the documentation but it make sense...

You can create CLIENT actions (every function definition you have in your controller) as well as server-side actions and the way that you create client-side actions, is exactly the same.

And it behaves in analogous manner, when executed, it executes the code of your invoked action. This action CAN RETURN a value, the value who is returned in the callback that you defined for that action and is retrievable throught response.getReturnValue();

An example:

quickTestApp.cmp

<aura:application >
    <c:quickTestCmp />
</aura:application>

quickTestCmp.cmp

<aura:component >
    <aura:attribute name="name" type="String" default="I dont remember my name" />

    <c:actionCallerCmp invokableAction="{!c.targetAction}" />   
</aura:component>

quickTestCmp.controller

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

        //var param1=event.getParam("param1");
        //var param2=event.getParam("param2");
        //I just leave this code here in case it ever works



        var ret=component.get("v.name");

        return JSON.parse(JSON.stringify(ret));//You really want to do this ugly practice if the data returned is not a primitive data
    }
})

actionCallerCmp.cmp

<aura:component >
    <aura:attribute name="invokableAction" type="Aura.Action" />

    <button type="button" onclick="{!c.callExternalAction}" >Try invokable clientSide actions</button>
</aura:component>

actionCallperCmp.controller

({
    callExternalAction : function(component, event, helper) {
        var clientSideAction=component.get("v.invokableAction"); //You get it from value provider because its passed by reference in the markup of this component

        if(clientSideAction){
                /*
            clientSideAction.setParams({
                param1:"im the param1",
                param2:"im the param2"
            });
            In previous releases, you were capable even to set params and the action was able to received it THIS NOT WORKS ATM (Spring '17)
            */
            clientSideAction.setCallback(this,function(response){
                var state=response.getState();
                if(state==="SUCCESS" && component.isValid()){
                    var ret=response.getReturnValue();
                    console.log("-WOOHHAA, I got it, the return of an old external action, lets see");
                    console.log("+"+ret)
                }
            });
            $A.enqueueAction(clientSideAction);
        }
    }
})

In the Lightning developer guide, there are no info about this feature of the aura framework, but it is in the official and complete reference of the framework, https://github.com/forcedotcom/aura/blob/master/aura_oss.pdf (Search for "Aura.Action")

After all, I absolutely advise against this practice due to a poor documentation about and the possibility they remove or change this from the Lightning implementation

Sorry for my english, its not my main.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .