21

I have tried several ways to do this and have not reached enlightenment.

I have the same problem as outlined in this question Navigation between components in lightning

I was optimistic about using navigateToUrl but only .app have available urls, and .app cannot be seen in the salesforce1 mobile application. The components are not available via a direct url.

Here is what I have found:


This works in an app but not in mobile:

$A.get("e.myNamespace:navigateToView").setParams({"view": "bar"}).fire();


For this I cannot figure out what my recordId is for my lighning component. BTW, Also tried "componentId": "xxx" which I found in Dave Carroll's sublime manifest file: $A.get("e.myNamespace:navigateToSObject").setParams({"recordId":"XXXXX2"}).fire();


The following also does not work:

$A.get("e.myNamespace:navigateToObjectHome").setParams({"scope":"myNamespace__expenseTracker__c"}).fire();


This works great and will take me to the homepage. I wish it worked for lightning components:

$A.get("e.force:navigateToURL").setParams({"url":"/_ui/core/chatter/ui/ChatterPage"}).fire();


Anybody familiar with a full lightning component example that demonstrations a navigation technique that works in salesforce mobile?

1
  • 1
    The detailed solution with explanation for component navigation can be found in the link below. force-base.com/2016/01/04/…
    – user25318
    Commented Feb 2, 2016 at 11:09

5 Answers 5

3

Seems there is an event missing from the documentation, I went through this last week. Try this..

Component markup

<ui:button label="ATTENDANCE" press="{!c.navigateToRollCall}"/>

Controller (I am using default namespace here for my component AttendanceRollCall)

navigateToRollCall : function(component, event, helper) {
    var evt = $A.get("e.force:navigateToComponent");
        evt.setParams({
            componentDef: "c:AttendanceRollCall",
            componentAttributes: {
                programId: component.get("v.program.Id")
            }
        });
    evt.fire();    
}
4
  • Can you give us some more context on how you got this to work? I can find no documentation about navigateToComponent and when I use this I get an internal error displayed that looks like this: <br />An internal server error has occurred<br/>Error ID: 1382860838-80715 (530229303)
    – waveforms
    Commented Feb 23, 2015 at 22:36
  • 4
    This appears to have stopped working now. According to Salesforce it was never officially supported. I haven't found an alternative yet. Commented Jun 3, 2015 at 7:43
  • 1
    It technically still works if you add the component you are trying to create into your markup, and surround it with an impossible condition. Like: <aura:if isTrue="{!false}"><c:AttendanceRollCall/></aura:if> Commented Aug 19, 2015 at 15:49
  • is there any working workaround guys for this?
    – VarunC
    Commented Nov 9, 2015 at 17:48
3

You could move between view states by creating and replacing components.

Server-side Controller

public class LightningController {

    @AuraEnabled
    public static list<Account> getAccounts(){
        return [SELECT Id, Name FROM Account LIMIT 10];
    }

    @AuraEnabled
    public static list<Opportunity> getOpportunities(Id AccountId){
        return [SELECT Id, Name FROM Opportunity WHERE AccountId = :AccountId];
    }

}

App

<aura:application controller="LightningController" >
    <aura:attribute type="Account[]" name="AccountList" />
    <aura:handler name="init" value="{!this}" action="c.doInit" />
    <aura:handler event="analysis:ATOEvent" action="{!c.ato}" />
    <aura:handler event="analysis:OTAEvent" action="{!c.ota}" />
    {!v.body}
</aura:application>

App client-side controller

({
    doInit : function(component, event, helper){
        var action = component.get("c.getAccounts");
        action.setCallback(this,function(response){
                if (response.getState() === "SUCCESS"){
                    component.set("{!v.AccountList}",response.getReturnValue());
                    helper.generateAccountList(component);
                }
            }
        );
        $A.enqueueAction(action);
    },
    ato : function(component, event, helper){
        var action = component.get("c.getOpportunities");
        action.setParams({"AccountId" : event.getParam("AccountId")});
        action.setCallback(this,function(response){
                if (response.getState() === "SUCCESS"){
                    helper.generateOpportunityList(component, response.getReturnValue());
                }
            }
        );
        $A.enqueueAction(action);
    },
    ota : function(component, event, helper){
        helper.generateAccountList(component);
    }
})

App helper

({
    generateAccountList : function(component) {
        $A.createComponent(
            "analysis:AccountList",
            {
                "AccountList" : component.get("{!v.AccountList}")
            },
            function(newComponent){
                component.set("v.body",newComponent);
            }
        )    
    },
    generateOpportunityList : function(component, OpportunityList){
        $A.createComponent(
            "analysis:OpportunityList",
            {
                "OpportunityList" : OpportunityList
            },
            function(newComponent){
                component.set("v.body",newComponent);
            }
        )
    }
})

AccountList

<aura:component >
    <aura:registerEvent name="ATOEvent" type="analysis:ATOEvent" /> 
    <aura:attribute name="AccountList" type="Account[]" />
    <aura:iteration items="{!v.AccountList}" var="Account">
        <ui:outputText value="{!Account.Name}" />
        <ui:button label="go" press="c.fireato" buttonTitle="{!Account.Id}" />
        <br/>
    </aura:iteration>
</aura:component>

AccountListController

({
    fireato : function(component, event, helper) {
        var action = $A.get("e.analysis:ATOEvent");
        action.setParams({"AccountId" : event.getSource().get("{!v.buttonTitle}")});
        action.fire();
    }
})

OpportunityList

<aura:component >
    <aura:registerEvent name="OTAEvent" type="analysis:OTAEvent" /> 
    <aura:attribute type="Opportunity[]" name="OpportunityList" />
    <ui:button label="Go Back" press="c.fireota" />
    <aura:iteration items="{!v.OpportunityList}" var="Opportunity" >
        <br />
        <ui:outputText value="{!Opportunity.Name}" />
    </aura:iteration>
</aura:component>

OpportunityListController

({
    fireota : function(component, event, helper) {
        var action = $A.get("e.analysis:OTAEvent");
        action.fire();
    }
})

ATOEvent

<aura:event type="APPLICATION" description="ATOEvent" >
    <aura:attribute name="AccountId" type="Id" />
</aura:event>

OTAEvent

<aura:event type="APPLICATION" description="OTAEvent" />
8
  • hello @martin - I tried your provided code as well but it is also throwing same 'Uncaught error in $A.run()' error when we click button to load another component. Is it working for you or just me having the issue?
    – VarunC
    Commented Nov 9, 2015 at 17:44
  • @VarunC It works for me. If you can show me where the error happened, I might be able to help you trouble-shoot.
    – martin
    Commented Nov 10, 2015 at 12:55
  • I'm getting following screen when I load the Lightning Sample App I created using the code above - link and then when I click Go button I get following error - error link
    – VarunC
    Commented Nov 10, 2015 at 16:03
  • Thanks to your comments @martin ... I'm able to find the issue. Actually I missed removing the namespace analysis from Events created in the code, and fixing that made the code working fine. Thanks a bunch for this workaround :-) ...
    – VarunC
    Commented Nov 10, 2015 at 16:38
  • @waveforms I think you should mark this post as an accepted answer, since the provided code works just fine after replacing the analysis namespace with c or your chosen namespace of the org and it solves the navigation of two lightning components as needed.
    – VarunC
    Commented Nov 10, 2015 at 16:40
3

Lightning component navigation has been re-defined in Winter'17 and we now have a native event to navigate through components.

Suppose you have a component named as MyComponent2.cmp and you want to navigate to this component from one of your existing components, then you can do it like this

NavigatetoC2 : function(component, event, helper) {
        var evt = $A.get("e.force:navigateToComponent");
        evt.setParams({
                componentDef : "c:MyComponent2",
                componentAttributes: {

                }
        });
        evt.fire();
}

The detailed solution for the same can be found in my latest post below

Lightning-component-Navigation-Winter'17

1
  • Hi Akhil, it's nice to have this functionality implemented but I am not able to have this its not responding any event on press of button. I am using Lighting out. Can u plz tell me is this functionality is available or not with lightning out. Commented Jan 9, 2017 at 8:34
2

The way to "navigate" from one component to another is to create and replace components within a container component. The container component can then be published to the Salesforce1 mobile app in a Lightning App created using the Lightning App Builder, or published to the web in a Lightning App created using the Developer Console.

It's a bit confusing (to me) because the term Lightning App is used twice to describe two different things. The Lightning App Builder "Lightning App" is mobile-only, and only available in the Salesforce1 mobile app. The Developer Console "Lightning App" is web-only, and available to anyone with a web browser and a Salesforce account, to which an admin has granted access to your app.

As noted on the Salesforce Developers Blog:

"What might not be obvious ... is that Salesforce1 is essentially what is known as a Single Page App or SPA." "In an SPA, page content is manipulated behind the scenes using client-side JavaScript, creating the appearance of separate pages."

https://developer.salesforce.com/blogs/developer-relations/2015/04/creating-lightning-components-1.html

0

This can now be accomplished via lightning:navigation documented here.

Summary

The target/ to component must implement lightning:isUrlAddressable interface and the source/ from component needs to include lightning:navigation, generate URL for a given pageReference (in this case to a custom component) and finally call the navigate method with that pageReference.

Here is a sample:

Target/ To Component

Component - myTarget.cmp

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,force:hasRecordId,lightning:isUrlAddressable">
    <lightning:card iconName="standard:settings" title="Navigation Example">
        <lightning:formattedText class="slds-p-left_small" value="This is your target component."/>
    </lightning:card>
</aura:component>

Source/ From Component

Component

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes">
    <lightning:navigation aura:id="navService"/>
    <lightning:button label="Navigate to Target Component" onclick="{!c.navigate}" />
</aura:component>

Controller JS

({
    navigate : function(component, event, helper) {
        var navService = component.find("navService");
        var pageReference = {
            "type": "standard__component",
            "attributes": {
                "componentName": "c__myTarget"
            }, 
            "state": {}
        };
        navService.navigate(pageReference);
    }
})

You must log in to answer this question.

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