trailhead

Iterate on Your Prototype

Learning Objectives

After completing this module, you’ll be able to:

  • Discuss iterations and limitations with stakeholders.
  • Add Salesforce data to your prototype.
  • Understand the importance of iteration in prototyping.

Let’s Get Feedback

Before we get too far along, let’s check back in with our stakeholders and make sure we’re on the right track with this prototype. By checking back with the designers and researchers often, we can ensure everyone is up to date on the latest progress and expectations.

This can also be a time to catch design flaws early. As prototypers, we’re the first users and testers, so we can make suggestions to the designers whenever something doesn’t feel quite right. Stakeholders can also be product managers (PMs) who have more knowledge about the technological feasibility of certain features. Having PMs involved can help ensure the prototype is realistic and manageable.

Time to Iterate

So your stakeholders had a lot of feedback on the prototype? Don’t worry...that’s expected. The key to prototyping is iteration. As Bryony Wilson from Empathy says, “Prototyping is like love. You don’t want to settle for the first one that comes along.” We rarely get everything right on the first try, because we, as designers and UXEs, are not our users. So we are bound to find usability gaps once we introduce the features to fresh eyes. In this scenario, the stakeholders are concerned the type of each card isn’t clear because every card looks the same and they are not easily scannable. Let’s iterate on that design before our research sessions to determine if we’re closer to the best possible solution.

Iterate on the Search Results Page

  1. In your Trailhead Playground, click the Setup Gear Icon setup gear icon and choose Developer Console
  2. In Developer Console, select File › Open Lightning Resources.
  3. Click c:ResultsSection to expand that section, click COMPONENT, and then click Open Selected.

Now the fun begins! Let’s iterate on the cards and add the iconName attribute to each Account card definition to indicate what category it belongs to:

  1. Find the following code (starting around line 6):
    <h2 class="slds-text-heading--medium slds-p-vertical--medium">Accounts</h2>
        
    <div class="slds-grid slds-col slds-size--1-of-1">
    <ul>
    <li class="slds-size--1-of-3 slds-show--inline-block">
    <lightning:card variant="narrow" class="slds-m-around--small">
  2. Add the following code to the lightning:card tag: iconName="standard:account".
  3. It should look like this: <lightning:card variant="narrow" iconName="standard:account" class="slds-m-around--small">
  4. Unfortunately, we have to repeat this for all of the Account cards. Maybe later we can make our prototype more scalable so we don’t have to go through this hassle.
  5. Click File > Save.
  6. Back in your org, refresh your Search Results page and bask in the glory of your beautiful new icons. Screen Shot showing Account cards now using an Account icon

Take It One Step Further—Bring on the Real Data!

But that just isn’t enough...let’s add in some real data to help bring our prototype to life. There can be risks with this, such as stakeholders thinking the feature or product is much more “done” than it actually is. So be sure to make it clear to your stakeholders that this is still a prototype.

Instead of having our dummy Account, Contact, and Lead data on the cards, let’s query the database for actual records.

Step 1: Write some Apex controllers

First we create simple Apex classes that return a list of accounts, contacts, and leads.

  1. In your Trailhead Playground, click the Setup Gear Icon setup gear icon and choose Developer Console.
  2. Click File › New › Apex Class.
  3. Enter the class name: SearchResultsController
  4. Replace all the code with the following code:
     public with sharing class SearchResultsController {
     @AuraEnabled
     public static List<Account> getAccounts() {
       List<Account> accounts = [SELECT Id, Name, Phone, Website, OwnerId FROM Account LIMIT 4];
       return accounts;
     }
     @AuraEnabled
     public static List<Contact> getContacts() {
       List<Contact> contacts = [SELECT Id, Name, Phone, Email, Title FROM Contact LIMIT 2];
       return contacts;
     }
     @AuraEnabled
     public static List<Lead> getLeads() {
       List<Lead> leads = [SELECT Id, Name, Company, Email, Status, Phone FROM Lead LIMIT 3];
       return leads;
     }
   }
  1. Click File > Save.
  2. Still in Developer Console, select File › Open Lightning Resources.
  3. Click c:ResultsSection to expand that section, click COMPONENT, and then click Open Selected.
  4. Let’s link the new apex controller by adding the following code to the top of our component file:
  5. On line 1, replace this code:
    <aura:component
    implements="force:appHostable,
    flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,
    force:hasRecordId,forceCommunity:availableForAllPageTypes,
    force:lightningQuickAction" access="global" >
  

with this code:

    <aura:component controller="SearchResultsController"
    implements="force:appHostable,flexipage:availableForAllPageTypes,
    flexipage:availableForRecordHome,force:hasRecordId,
    forceCommunity:availableForAllPageTypes,
    force:lightningQuickAction" access="global" >
  
  1. Next, insert a new line after Line 1 in order to declare our variables and initialization function.
  2. Copy and paste the following code:
    <aura:attribute name="accounts" type="Account[]"/>
    <aura:attribute name="contacts" type="Contact[]"/>
    <aura:attribute name="leads" type="Lead[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

Step 2: Create the JavaScript helpers

Next we add JavaScript helpers, which will call our Apex code, get the appropriate data from the database, and put the data into the corresponding variables that we just declared.

  1. Click the Helper option on the right panel.
  2. Replace the placeholder code with the following code:
  ({
    getAccounts : function(cmp) {
      var action = cmp.get("c.getAccounts");
      action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
          cmp.set("v.accounts", response.getReturnValue());
        }
      });
      $A.enqueueAction(action);
    },
    getContacts : function(cmp) {
      var action = cmp.get("c.getContacts");
      action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
          cmp.set("v.contacts", response.getReturnValue());
        }
      });
      $A.enqueueAction(action);
    },
    getLeads : function(cmp) {
      var action = cmp.get("c.getLeads");
      action.setCallback(this, function(response){
        var state = response.getState();
        if (state === "SUCCESS") {
          cmp.set("v.leads", response.getReturnValue());
        }
      });
      $A.enqueueAction(action);
    },
  })
  1. Click File > Save.

Step 3: Create the JavaScript controller

Next we add a JavaScript initialization function to the controller, which will connect our UI to our new Helper functions to complete the flow of data.

  1. Click the Controller option on the right panel.
  2. Replace all the code with the following code:
  ({
    doInit : function(component, event, helper) {
      helper.getAccounts(component);
      helper.getContacts(component);
      helper.getLeads(component);
    }
  })
  1. Click File > Save.

Step 4: Update the UI to use the real data

Next, we bring it all together by using the aura:iteration tags to iterate over our real data and display it in the UI, thus making our prototype scalable for future changes.

  1. Click the Component option on the right panel.
  2. Replace all the code with the following code:
  <aura:component controller="SearchResultsController" implements="force:appHostable,
  flexipage:availableForAllPageTypes,
  flexipage:availableForRecordHome,force:hasRecordId,
  forceCommunity:availableForAllPageTypes,
  force:lightningQuickAction" access="global" >
    <aura:attribute name="accounts" type="Account[]"/>
    <aura:attribute name="contacts" type="Contact[]"/>
    <aura:attribute name="leads" type="Lead[]"/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <div class="slds-card">
      <h2 class="slds-text-heading--medium slds-p-vertical--medium">Accounts</h2>
      <div class="slds-grid">
        <ul class="slds-col slds-size--1-of-1">
          <aura:iteration items="{!v.accounts}" var="account">
            <li class="slds-size--1-of-3 slds-show--inline-block">
              <lightning:card variant="narrow" iconName="standard:account" class="slds-m-around--small  slds-card_boundary">
                <aura:set attribute="title">
                  {!account.Name}
                </aura:set>
                <div class="slds-tile slds-p-horizontal--large">
                  <div class="slds-tile__detail slds-text-body--small">
                    <dl class="slds-list--horizontal slds-wrap">
                      <dt class="slds-item--label slds-text-color--weak slds-truncate" title="First Label">Phone:</dt>
                      <dd class="slds-item--detail slds-truncate">{!account.Phone}</dd>
                      <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Second Label">Website:</dt>
                      <dd class="slds-item--detail slds-truncate">{!account.Website}</dd>
                      <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Third Label">Account Owner:</dt>
                      <dd class="slds-item--detail slds-truncate">{!account.OwnerId}</dd>
                    </dl>
                  </div>
                </div>
              </lightning:card>
            </li>
          </aura:iteration>
        </ul>
      </div>
      <h2 class="slds-text-heading--medium slds-p-vertical--medium">Contacts</h2>
      <div class="slds-grid">
        <ul class="slds-col slds-size--1-of-1">
          <aura:iteration items="{!v.contacts}" var="contact" indexVar="index">
            <li class="slds-size--1-of-3 slds-show--inline-block">
              <lightning:card variant="narrow" class="slds-m-around--small  slds-card_boundary">
                <aura:set attribute="title">
                  {!contact.Name}
                </aura:set>
                <div class="slds-tile slds-p-horizontal--large">
                  <div class="slds-tile__detail slds-text-body--small">
                    <dl class="slds-list--horizontal slds-wrap">
                      <dt class="slds-item--label slds-text-color--weak slds-truncate" title="First Label">Email Address:</dt>
                      <dd class="slds-item--detail slds-truncate">{!contact.Email}</dd>
                      <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Second Label">Title:</dt>
                      <dd class="slds-item--detail slds-truncate">{!contact.Title}</dd>
                      <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Third Label">Phone:</dt>
                      <dd class="slds-item--detail slds-truncate">{!contact.Phone}</dd>
                    </dl>
                  </div>
                </div>
              </lightning:card>
            </li>
          </aura:iteration>
        </ul>
      </div>
      <h2 class="slds-text-heading--medium slds-p-vertical--medium">Leads</h2>
      <div class="slds-grid">
        <ul class="slds-col slds-size--1-of-1"> <aura:iteration items="{!v.leads}" var="lead" indexVar="index">
          <li class="slds-size--1-of-3 slds-show--inline-block">
            <lightning:card variant="narrow" class="slds-m-around--small  slds-card_boundary">
              <aura:set attribute="title">
                {!lead.Name}
              </aura:set>
              <div class="slds-tile slds-p-horizontal--large">
                <div class="slds-tile__detail slds-text-body--small">
                  <dl class="slds-list--horizontal slds-wrap">
                    <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Second Label">Company:</dt>
                    <dd class="slds-item--detail slds-truncate">{!lead.Company}</dd>
                    <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Second Label">Email Address:</dt>
                    <dd class="slds-item--detail slds-truncate">{!lead.Email}</dd>
                    <dt class="slds-item--label slds-text-color--weak slds-truncate" title="Third Label">Status:</dt>
                    <dd class="slds-item--detail slds-truncate">{!lead.Status}</dd>
                    <dt class="slds-item--label slds-text-color--weak slds-truncate" title="First Label">Phone:</dt>
                    <dd class="slds-item--detail slds-truncate">{!lead.Phone}</dd>
                  </dl>
                </div>
              </div>
            </lightning:card>
          </li>
        </aura:iteration>
      </ul>
    </div>
  </div>
</aura:component>
  1. Click File > Save.

Ready to see the magic? Go back in your org, refresh your Search Results page. You should see some real data lighting up your prototype. Screen shot showing final prototype with icons and realistic text in the cards

Now that we have a more realistic, scalable prototype using real data, it’s time to do some user testing with our researchers.

Note

Note

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

Resources

retargeting