5

In my lightning component I loop over records and display links to them:

1) Works, but is discouraged as it doesn't work in all places

<aura:iteration items="{!v.records}" var="record">
    <a href="{!'/' + stage.id}" />
</aura:iteration

2) Tried that but fails with:

Cannot mix expression and literal string in attribute value

<aura:iteration items="{!v.records}" var="record">
    <a onlick="sforce.one.navigateToSObject({!'/' + stage.id})" />
</aura:iteration

3) How to pass the recordId into myOwnNavigateToSObject()?

<aura:iteration items="{!v.records}" var="record">
    <a onlick="{!c.myOwnNavigateToSObject}" />
</aura:iteration

My preferred solution is to make 2) work as I see no use of an additional controller function that just delegates work to navigateToSObject().

  • 2
    Option 1 should work "everywhere". Do you have a link to any documentation that suggests otherwise? – sfdcfox May 31 '17 at 16:28
  • 1
    @sfdcfox: See the Trailhead trailhead.salesforce.com/en/modules/lex_dev_visualforce/units/… where they say: "Don’t use static URLs to Salesforce resources. That is, if you’re adding a link to edit a Contact record, don’t create the link by building a string with a static pattern like link = '/' + accountId + '/e'. In some contexts this works, but in others it doesn’t. Instead, try one of these approaches:" – Robert Sösemann Jun 1 '17 at 8:23
5

Thanks to all the other "answers" I finally solved it myself. To make it work with:

  • Summer '17 activated Locker-Service
  • regular <a> links AND <lightning:button> base components

I use id= for <a> and value= for <lightning:button>:

<aura:iteration items="{!v.records}" var="record">
    <a id="{!record.Id}" onclick="{!c.navigateToSObject}" />
    <lightning:button value="{!record.Id}" onclick="{!c.navigateToSObject}" />
</aura:iteration>

The controller need to check if getSource is defined and use event.currentTarget instead of event.target in case it is not.

navigateToSObject: function(cmp, event, helper) {
    var recordId = (event.getSource != undefined) ? event.getSource().get("v.value") 
                                                  : event.currentTarget.id;
    var evt = $A.get("e.force:navigateToSObject");
    evt.setParams({
        "recordId": recordId,
        "slideDevName": "detail"
    });
    evt.fire(); 
}
  • 2
    Just a thought you can kind of have different methods on a tag and button and from there call a common method which will fire the event. This will give you better control incase you want to add more logic between an a tag and button – RedDevil Jun 1 '17 at 8:43
  • 1
    Sure thing! If I build a generic lib to solve this i would definitly have to work on making this more generic. – Robert Sösemann Jun 1 '17 at 8:50
1

Try this

<aura:iteration items="{!v.records}" var="record">
<a id="{!record.Id}" onclick="{!c.myOwnNavigateToSObject}" />
</aura:iteration

an then in the controller:

myOwnNavigateToSObject: function(component, event, helper){
    var idx = event.target.id;        
    var sObectEvent = $A.get("e.force:navigateToSObject");
    sObectEvent .setParams({
    "recordId": idx  ,
    "slideDevName": "detail"
    });
    sObectEvent.fire(); 
},
  • Really verbose compared to Visualforce, but ok. How would that work I I have <lightning:button> instead of <a> tags. They are not allowed to add an id attribute? – Robert Sösemann May 31 '17 at 14:22
  • You could use the "value" attribute – Acabo May 31 '17 at 14:55
  • No, sorry, I have tested it and you can't do that with a lightning:button. You can see some solutions here: salesforce.stackexchange.com/questions/147166/… – Acabo May 31 '17 at 15:13
  • Even "event.target.id" evaluates to null. :-( – Robert Sösemann May 31 '17 at 18:39
  • If you're binding events to the component (e.g. lightning:button) instead of an HTML element, you can get the event source via event.getSource().You can't add an "id" attribute to it, but you can add a local "aura:id", which can later be retrieved via event.getSource().getLocalId(). More info here. – Pawel Fronczak May 31 '17 at 20:21
1

2) won't work not only due to mixing expressions and literals but primarily because any arbitrary Javascript placed in the component markup is ignored by the framework. As described here:

Any browser DOM element event starting with on, such as onclick or onkeypress, can be wired to a controller action. You can only wire browser events to controller actions.

You can pass the id somewhere in the link markup (id or data-* attributes) as described by Acabo.

A more "component-oriented" approach would be to create a separate component for the item and in that component's controller invoke navigateToSObject in the context of that single record. Something along the lines of:

<aura:iteration items="{!v.records}" var="record">
    <c:item record="{!record}"/>
</aura:iteration

And in the item component:

<aura:attribute name="record" type="SObject" />

<a onlick="{!c.navigate}" />

Now your custom navigate method operates in the context of a single record.

  • 1
    Creating an extra component just to call an URL seems so much to much that this is not a solution at all. Sorry. – Robert Sösemann May 31 '17 at 14:23
  • You may not like it, but that's the proper "Lightning" way about it :). And while it may be indeed too much for a simple button, it structures your app into nice encapsulated components. – Pawel Fronczak May 31 '17 at 20:18

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.