trailhead

Create and Edit Lightning Components

Learning Objectives

After completing this unit, you’ll be able to:
  • Create and edit Lightning component bundle resources in the Developer Console.
  • Create a “harness” application for testing components in development.
  • Perform the edit and reload cycle for previewing components in development.
  • List the different resources that make up a Lightning component bundle.

Creating and Editing Lightning Components

OK! Time to write some code! #finally!

The first step to writing Lightning Components code is, uh, getting set up to write code. Fortunately, this is really easy. In your org, open the Developer Console under Your Name or the quick access menu (Setup gear icon).

Lightning Experience Salesforce Classic

Opening the developer console

Classic mode: Opening the developer console

Boom, you’re ready to write Lightning Components code!

Boom: you can start writing component code

Create Lightning Components in the Developer Console

So, let’s write something. Select File | New | Lightning Component to create a new Lightning component. In the New Lightning Bundle panel, enter helloWorld for the component name, and click Submit.

New Lightning Bundle panel

This creates a new helloWorld component bundle, with two open tabs. Close the helloWorld tab, and keep the helloWorld.cmp tab open.

helloWorld.cmp contains the opening and closing tags for a Lightning component, <aura:component>. Between them, add the following markup, and save:

<p>Hello Lightning!</p>

Your component markup should look like the following.

Hello Lightning markup

Woohoo, your first Lightning component! Now…how do we see what it looks like?

The short answer is, it’s tricky. You can’t run your component directly and see how it behaves. Instead, your component needs to run inside a container app, which we’ll call a container for short. Examples of containers would be the Lightning Experience or Salesforce apps, or an app you build with Lightning App Builder—basically, any of the things you saw at the end of the prior unit. You add your component to one of these containers, and then access it within that container.

We’ll talk more about containers later, and in other Lightning Components modules. For now, let’s just make a simple one of our own.

Select File | New | Lightning Application to create a new Lightning app. In the New Lightning Bundle panel, enter “harnessApp” for the app name, and click Submit.

This creates a new harnessApp bundle, with two open tabs. Close the harnessApp tab, and keep the harnessApp.app tab open.

harnessApp.app contains the opening and closing tags for a Lightning app, <aura:application>. Between them, add the following markup, and save:

<c:helloWorld/>

This adds the helloWorld component we created earlier to the harnessApp app.

Before we explain this deceptively simple app, click back and forth between the harnessApp.app and helloWorld.cmp tabs in the Developer Console. Besides the markup, what do you notice that’s different?

What is different?

Got it in one: the Preview button. Apps have one, components don’t. Click it now, and another browser window should open and show you your app.

Preview the app.

Now we’re cooking with…well, OK, it’s just “hello world.” But there are some interesting things to notice here, in spite of the markup being trivial.

Let’s start with the Developer Console. If you’ve used it to write Visualforce or Apex, you have surely noticed the extra controls that appear in a palette on the right side of the editing window of any Lightning bundle. Each of the different buttons with a Create label represents a different resource you can add to the bundle. We’ll talk about resources and bundles in the next section. For now, just know that the Developer Console gives you an easy way to create and switch between them.

Indeed, the Developer Console has a number of features for working with Lightning Components. There’s also File | Open | Lightning Resources, which lets you open a bunch of Lightning resources all at once. Useful!

The Developer Console is a fine place to write Lightning code, and we’ll work with it for the rest of this module. But, because Lightning resources are accessible via the Tooling API, there are other ways to create and edit them. Salesforce DX provides robust support for all aspects of developing Lightning components. The Force.com IDE is a good stand-alone client, and there are excellent third-party tools such as Sublime Lightning and VS Code. Don’t feel like you’re limited to just the Developer Console!

One last thing before we turn to the code. The URL for our “preview” is actually the permanent home of our app (once it’s made available to our users). The format of the URL is the following: https://<yourDomain>.lightning.force.com/<yourNamespace>/<yourAppName>.app.

<yourAppName> represents the name of your app bundle, in this case, harnessApp. In your Trailhead org you shouldn’t have a namespace configured, so you should see a “c” in that part of the URL. “c” represents the default namespace…and it will come back to haunt us later. The rest of the URL format should be self-explanatory.

OK, on to the code!

What Is a Component?

It’s not often that hello world triggers existential questions, but here we are. Let’s talk about what a component is in the context of our helloWorld example. As a practical matter, a component is a bundle that includes a definition resource, written in markup, and may include additional, optional resources like a controller, stylesheet, and so on. A resource is sort of like a file, but stored in Salesforce rather than on a file system.

Our helloWorld.cmp component definition resource is easy to understand.

<aura:component>
    <p>Hello Lightning!</p>
</aura:component>

There are the opening and closing <aura:component> tags, with some static HTML in between. It would be hard to be more simple, and you might be tempted to think of it as a “page.” Don’t. We’ll come back to this in a bit.

We’ve mentioned component bundles already, but what are they really? A bundle is sort of like a folder. It groups the related resources for a single component. Resources in a bundle are auto-wired together via a naming scheme for each resource type. Auto-wiring just means that a component definition can reference its controller, helper, etc., and those resources can reference the component definition. They are hooked up to each other (mostly) automatically.

Let’s see how this works. With helloWorld.cmp active, click the STYLE button in the component palette on the right. This opens a new tab for the style resource that was added to the helloWorld bundle. It starts with a single, empty selector, .THIS. To see how this works, add a simple style to the stylesheet, so that it looks like the following.

.THIS {
}

p.THIS {
    font-size: 24px;
}

Then reload your preview window for harnessApp.app. Voilà, larger text! But, how does .THIS work? It’s the magic of auto-wiring! At runtime .THIS is replaced with a style scoping string named for your component. It limits style rules to only this component, so that you can create styles that are specific to the component, without worrying about how those styles might affect other components.

So now our helloWorld bundle has two resources, the component definition, helloWorld.cmp, and the stylesheet, helloWorld.css. You can think of it like a folder, or an outline:

  • helloWorld — the component bundle
    • helloWorld.cmp — the component’s definition
    • helloWorld.css — the component’s styles

As you can see in the Developer Console, there are a number of other resource types you can add to a component bundle. Go ahead and click the CONTROLLER and HELPER items to add those resources to the bundle. Now your bundle looks something like this, and you can start to see the naming system.

  • helloWorld — the component bundle
    • helloWorld.cmp — the component’s definition
    • helloWorldController.js — the component’s controller, or main JavaScript file
    • helloWorldHelper.js — the component’s helper, or secondary JavaScript file
    • helloWorld.css — the component’s styles

In this module, we’ll work with only these four resource types. We’ll talk a lot more about the controller and helper resources when we actually start writing code for them. For now, you can just leave the default implementations. After all, this is just hello world!

What Is an App?

Now that we know what a component is, it’s actually easy to explain what an app is—an app is just a special kind of component! For the purposes of this module, you can think of an app as being different from a component in only two meaningful ways:

  • An app uses <aura:application> tags instead of <aura:component> tags.
  • Only an app has a Preview button in the Developer Console.

That’s it!

What Are Apps For?

As simple as that sounds, there are a few practical details in how you can use an app vs. a component. The main items are the following.

  • When writing markup, you can add a component to an app, but you can’t add an app to another app, or an app to a component.
  • An app has a standalone URL that you can access while testing, and which you can publish to your users. We often refer to these standalone apps as “my.app.”
  • You can’t add apps to Lightning Experience or the Salesforce app—you can only add components. After the last unit this might sound weird; what exactly do you add to the App Launcher, if not an app? What you add to App Launcher is a Salesforce app, which wraps up a Lightning component, something defined in a <aura:component>. A Lightning Components app—that is, something defined in a <aura:application> —can’t be used to create Salesforce apps. A bit weird, but there it is.

So, what’s an app good for? Why would you ever use one? We answered that question earlier. You publish functionality built with Lightning Components in containers. Lightning Components apps are one kind of container for our Lightning components.

Once again being practical, this usually means that you build all of your “app” functionality inside a top-level component. Then at the end, you stick that one component in a container—maybe a Lightning Components app, maybe the Salesforce app, maybe something else. If you use a my.app, the container can set up services for your main component, but otherwise it’s just there to host the component.

Let’s take another look at the app we created. Here again is the harnessApp.app definition resource:

<aura:application>
	  
    <c:helloWorld/>
	    
</aura:application>

No matter how much functionality we decide we’re going to add to our helloWorld “app”, it’s all going to go inside the helloWorld component. It could have a Quip-style editor embedded in it for revising the hello message, but our harnessApp.app definition is going to remain pretty much this simple.

From here on, we’ll assume that you’re using an actual Lightning Application bundle as just a container, or harness, for components you create. Feel free to keep using harnessApp.app! But, when we talk about creating apps, we really mean building functionality inside a component bundle, not an application bundle, because that’s how you build “apps” in the real world.

Components Containing Components, Containing…Components!

The harnessApp.app definition is also interesting because instead of static HTML we have our helloWorld component. We say that harnessApp contains the helloWorld component. Let’s dive into this a little bit, and make helloWorld a little more complex.

In the Developer Console, create a new Lightning component named helloHeading. For its markup, paste in the following code.

<aura:component>
    <h1>W E L C O M E</h1>
</aura:component>

Now, click back to helloWorld.cmp, and add <c:helloHeading/> to it, above the “Hello Lightning” line. Your helloWorld component definition should now look like this:

<aura:component>
	  
    <c:helloHeading/>
	    
    <p>Hello Lightning!</p>
	    
</aura:component>

Reload the app to see the change. Your component structure, in terms of what contains what, now looks like this:

  • harnessApp.app
    • helloWorld.cmp
      • helloHeading.cmp
      • (static HTML)

We say that helloHeading is a child component of helloWorld, or that helloHeading is nested inside helloWorld, or…. There are any number of different ways to say that helloWorld contains helloHeading. What’s more, you can keep nesting components inside other components down to pretty much any level you’d care to. It starts being too hard to keep straight in your head well before you run into a limitation of Lightning Components!

This process of putting components inside each other is fundamental to building Lightning Components apps. You start with, or build, simple, “fine-grained” components, where each component provides a defined set of self-contained functionality. Then you assemble those components into new components with higher-level functionality. And then you use those components, and “level up” again.

Let’s talk about that with a metaphor that’s familiar to us outside of the software context. Imagine a house. Better yet, let us show you one. House animation

When you look at this house, what do you see? If you stop thinking of it as a “house”, but as a house component, you also start to see the pieces and patterns it’s made of.

At the largest scale, this house is composed of three similar structures. Those three components have similar, but not identical designs. Each can be broken down further, into even smaller components, such as windows, which can be broken down into individual panes. The arrangement, or composition, of these smaller components defines the differences between the three larger structures.

The three structures are joined together by two smaller, narrow structures/components, which can themselves be broken down into smaller, reusable patterns. These connecting components bring the three separate structures together into a larger whole: The House.

As we did with architecture, so we can do with a web app. Later in this module you’ll take fine-grained input components and create a form component with them. Then you’ll take that form component and put it into another component, to build up to app-level functionality. Expenses app composition

It’s not as pretty to look at as the house, but the principles behind the composition process are very similar. Thinking in terms of components, and composition, is a fundamental skill you’ll develop throughout this module, and whenever you build apps with Lightning Components.

You’ve done a little bit of that here, but before we can really build components that do something, we need to learn about attributes, types, values, and expressions. Before that, though, your first code challenge!

Resources

Lightning bolt icon used to indicate that the content is for Lightning Experience

Remember, this module is meant for Lightning Experience. When you launch your hands-on org, switch to Lightning Experience to complete this challenge.

retargeting