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
  • 2
    Option 1 should work "everywhere". Do you have a link to any documentation that suggests otherwise?
    – sfdcfox
    Commented May 31, 2017 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:" Commented Jun 1, 2017 at 8:23

3 Answers 3

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
  • 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
    Commented Jun 1, 2017 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. Commented Jun 1, 2017 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(); 
},
5
  • 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? Commented May 31, 2017 at 14:22
  • You could use the "value" attribute
    – Acabo
    Commented May 31, 2017 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
    Commented May 31, 2017 at 15:13
  • Even "event.target.id" evaluates to null. :-( Commented May 31, 2017 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. Commented May 31, 2017 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.

2
  • 1
    Creating an extra component just to call an URL seems so much to much that this is not a solution at all. Sorry. Commented May 31, 2017 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. Commented May 31, 2017 at 20:18

You must log in to answer this question.

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