forcedotcom / aura

This project is archived, please see the readme for additional resources.
Apache License 2.0
674 stars 333 forks source link

Cannot set event handler on a Managed Package component #173

Closed angelsalazar-zz closed 5 years ago

angelsalazar-zz commented 6 years ago

Hello,

I just created a managed package (it's currently a beta version) where a I have a bundle of reusable components I have developed.

I was testing them before to release the package and I am having an issue with the components that fire component events.

Gateway component

<aura:component description="Gateway" access="global">
    <!-- attributes -->
   <aura:attribute name="permissionName" required="true" access="global"/>

   <!-- registered events -->
   <aura:registerEvent name="onPermissionGranted" type="c:Gateway_Evt"/>
   <aura:registerEvent name="onPermissionDenied" type="c:Gateway_Evt"/>
   <aura:registerEvent name="onError" type="c:Gateway_Evt"/>

   <!-- markup -->
</aura:component>

Gateway_Evt component

<aura:event type="COMPONENT" description="Event template" access="global"/>

When trying to set a handler for onPermissionGranted event

<MyNameSpace:Gateway
  permissionName="adminAccess"
  onPermissionGranted="{! c.onGranted }"
/>

the aura library throws the following error

Failed to save PG.app: An unexpected error occurred. Please include this ErrorId if you contact support: 382966750-5258 (1999603462)

The error is not helpful at all, I am wondering why does the aura library not allow me to set an event handler?

the components have API version 43

no-stack-dub-sack commented 6 years ago

Any news on this??? I'm having the same exact issue and am no closer to solving the problem.

@angelsalazar did you ever find a solution? This is the only other issue I can find that seems similar.

angelsalazar-zz commented 6 years ago

@no-stack-dub-sack No, I am still having the issue when using a managed package, but it does not happen when using unlocked packages.

no-stack-dub-sack commented 6 years ago

@angelsalazar very interesting. I was wondering that myself. But with un-managed packages, you lose the benefit of being able to keep the code isolated, right? Developers in the installation org can modify the code of the un-managed package components, and fold that code in to the org's repository, right?

@byao might you or any other contributors know anything about this or be able to offer any suggestions about what the issue might be here? A couple of other developers on my team have also looked into the issue, and we're all scratching our heads, because it seems quite simple, and yet does not work.

no-stack-dub-sack commented 6 years ago

@angelsalazar try this:

<aura:handler 
    name="onPermissionGranted"
    event="MyNameSpace.Gateway_Evt"
    action="{! c.onGranted}" />

<MyNameSpace:Gateway permissionName="adminAccess" />

This is apparently the right way to handle the events. Not by passing them by name in the component markup. What kills me, is why that works in the first place, when you are outside of the managed package context? It should only work one way or the other. But for some reason it works the WRONG way under normal circumstances. Carefully read the documentation here.

Worked like a charm in my case.

angelsalazar-zz commented 6 years ago

Hi @no-stack-dub-sack, thank you, I knew I could handle the event using aura:handler. Another way to handle them is creating your component using $A.createComponent

like

$A.createComponent(
  'MyNameSpace:Gateway', 
  {
    onPermissionGranted : component.getReference('c.onGranted')
  },
  $A.getCallback(function (gatewayComponent) { 
     component.set('v.gatewatFacet', gatewayComponent);
  })
)

the action handler will work just fine.

Personally, I do not like to handle my events using aura:handler tag for the following main reasons :

I personally believe it is a bug because if you use attribute type Aura.Action and specify the action handler on the component markup and it just will work just fine.

if handling the event by passing the action handler in the component is a bad practice, why does the components under the lightning namespace support them in the first place?.

no-stack-dub-sack commented 5 years ago

@angelsalazar apparently it is not bad practice, and I'm back to thinking this is a bug as well: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/events_component_handling_child.htm

However, in my case, handling the event with an aura:handler tag allows the benefit of having the managed package. I do agree that its better to handle the events as in your original example, though, and I've filed a ticket with SF, so maybe I'll get some resolution out of them. If so, I'll be happy to share it here.

no-stack-dub-sack commented 5 years ago

@angelsalazar curious, can you point me to a lightning namespaced component that accepts event handlers inline? I'd like to take a look at the source code. I looked through several and didn't find any that take functions as parameters

angelsalazar-zz commented 5 years ago

you can find them on the following link

https://developer.salesforce.com/docs/component-library/

no-stack-dub-sack commented 5 years ago

@angelsalazar thanks, I was looking through a bunch of them there the other day, but couldn't find any that accept functions in this way. Was just wondering if you knew anyone in particular off the top of your head. No worries, though.

angelsalazar-zz commented 5 years ago

Most of the lightning components accept them

lightning:button has an onclick event

<lightning:button label="Neutral" title="Neutral action" onclick="{! c.handleClick }"/>

lightning:accordion has on onsectiontoggle event

<lightning:accordion
        allowMultipleSectionsOpen="true"
        onsectiontoggle="{! c.handleSectionToggle }"
        activeSectionName="{! v.activeSections }"
    >
        <lightning:accordionSection name="A" label="Accordion Title A">
            <aura:set attribute="actions">
                <lightning:buttonMenu aura:id="menu" alternativeText="Show menu" menuAlignment="right" iconSize="x-small">
                    <lightning:menuItem value="New" label="Menu Item One" />
                    <lightning:menuItem value="Edit" label="Menu Item Two" />
                </lightning:buttonMenu>
            </aura:set>
            <aura:set attribute="body">
                <p>This is the content area for section A.</p>
                <p>.</p>
                <p>.</p>
                <p>.</p>
                <p>The section height expands to fit your content.</p>
            </aura:set>
        </lightning:accordionSection>
        <lightning:accordionSection name="B" label="Accordion Title B">
                <p>This is the content area for section B.</p>
                <p>.</p>
                <p>.</p>
                <p>.</p>
                <p>The section height expands to fit your content.</p>
        </lightning:accordionSection>
        <lightning:accordionSection name="C" label="Accordion Title C">
                <p>This is the content area for section C.</p>
                <p>.</p>
                <p>.</p>
                <p>.</p>
                <p>The section height expands to fit your content.</p>
        </lightning:accordionSection>
    </lightning:accordion>

lightning:input has onchange event lightning:combobox has onchange event, etc.

no-stack-dub-sack commented 5 years ago

@angelsalazar oh whoops, I think I was looking at the UI namespaced components since the source code for those is here in this repo. perfect, thank you.

Interestingly, if you look at the source for lightning:button, for example, by inspecting the sources on the docs page (you can only see it as one JS file, but the component markup is there too, just all parsed out into its individual pieces), you can see that they're actually handling this a little differently. They are passing the functions down as attributes with type Aura:Action, and then creating the event in the handler:

image

this is a list of component attribute definitions in the parsed markup section of the JS object: image

So its not really using the same inline event handling syntax that is causing an issue here. This doesn't solve the problem in any way, but I suppose helps me understand why they can do it effectively and yet it seems so problematic in this case. I also wonder if they're handling it like this because this is an (internally) known limitation of using the framework for managed packages.