19

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
    The detailed solution with explanation for component navigation can be found in the link below. force-base.com/2016/01/04/… – user25318 Feb 2 '16 at 11:09
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();    
}
  • 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 Feb 23 '15 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. – Bob Buzzard Jun 3 '15 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> – Moshe Karmel Aug 19 '15 at 15:49
  • is there any working workaround guys for this? – VarunC Nov 9 '15 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" />
  • 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 Nov 9 '15 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 Nov 10 '15 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 Nov 10 '15 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 Nov 10 '15 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 Nov 10 '15 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

  • 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. – Dheeraj_Vashist Jan 9 '17 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);
    }
})

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.