Post on 02-Dec-2014
description
Salesforce1 Events App on AngularJS in Two WeeksPeter Chittum
Developer Evangelist
salesforce.com
@pchittum
Adrian Smalley
Lead Salesforce Architect
Acumen Solutions
@adriansmalley
Safe Harbor
Safe harbor statement under the Private Securities Litigation Reform Act of 1995:
This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services.
The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of any litigation, risks associated with completed and any possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-K for the most recent fiscal year and in our quarterly report on Form 10-Q for the most recent fiscal quarter. These documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site.
Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.
Peter ChittumDeveloper Evangelist@pchittumgithub.com/pchittum
Adrian SmalleyLead Salesforce Architect - UK
@adriansmalley
2 Min DEMOAdrian : EventFlex
EventFlexBefore we begin….
• This app is open source and an accelerator for those wishing to take it further.
• It is hosted on github : https://github.com/adriansmalley/eventflex
• Showcases cool features but isn’t quite production ready. You have been warned.
Our ApproachAdrian : Begin with the end in mind
TimelineAcumen’s approach to custom SF1 App creation
1 2 3 4 5 6 7 8 9 10
UX SF1 Config Angular App Data Layer Front end Dev
Initiate Define Build Deliver Launch
Who and How?!The criticalness of UX and Wireframing
Team
Tools
Solution
?!
UX & BA Admin Angluar & SF DEV
Balsamiq
Google Docs
Github
Git Issues
UX
Step 1 : Persona’s, Design, Style, UXAdrian : Bringing user experience to the centre of app development
Have the user at the heart and the startThinking about User Experience from the beginning
# 1# 2# 3
1. Personas 2. Stories 3. Prioritise Stories
4. User Flows 5. Wireframes 6. Design
UX
Begin with the end in MindThe criticalness of UX and Wireframing
4 Version of this screen before deciding
Choosing Charts before development
Single attempt at Build!
UX
Visualforce on Salesforce1Peter : Connecting Angular, Salesforce1, and Visualforce
Salesforce1 MobileExtensible Hybrid Mobile App
• Point and Click• Visualforce• Canvas• NEW! Lightning Components
Salesforce1
Salesforce1 + Visualforce
• Publisher Action• Visualforce Tab• Mobile Card
Salesforce1
Your Visualforce Page in Salesforce1
<!-- Visualforce Basic Page Setup --><apex:page docType="HTML-5.0" showHeader="false" sidebar="false"
standardStylesheets="false" controller="EventFlexServices">
<!-- use static resources --><apex:includeScript value="{!URLFOR($Resource.efLibs,'angular/angular.min.js')}" />...<apex:stylesheet value="{!URLFOR($Resource.efLibs,
'bootstrap1/css/bootstrap.min.css')}"/>
Salesforce1
Angular App ArchitecturePeter : Angular in SFDC
BASE HTMLPAGE
App Structure
APEX Classes
JAVASCRIPT• APP STARTUP• DIRECTIVES• CONTROLLERS• SERVICES
ANGULARJS MODULE LIBS
CSS
HTML VIEWS (PARTIALS)
VISUALFORCEPAGE
Static ResourcesStatic Resources
Static ResourcesStatic Resources/Bundle
AngularJS App
Static Resource Mapping
var staticItems = { 'efMainHTML' : "{!URLFOR($Resource.efMainHTML)}", 'efSessionHTML' : "{!URLFOR($Resource.efSessionHTML)}", ... 'getSessionTopics':'{!$RemoteAction.EventFlexServices.getSessionTopics}', 'getSessionSpeakers' : '{!$RemoteAction.EventFlexServices.getSessionSpeakers}’, ...};
AngularJS App
The Components
VISUALFORCE
ANGULARJS
BOOTSTRAP(-SF1)
The “VAB” Stack
AngularJS App
Why AngularJS
• Structured JS• Convention creates familiarity• Adaptable, Extensible• Big community• Enterprise ready
AngularJS App
AngularJS App Startup
var eventFlex = angular.module('eventflex', ['ngRoute', 'ngAnimate', 'gantt']);
<div class="container-fluid" ng-app="eventflex"><div ng-view="#" class="slide container"></div>
</div>
App Name Included Modules
AngularJS App
AngularJS Page Views & RoutingPage UI templates
eventFlex.config(function($routeProvider) { $routeProvider .when('/', { templateUrl : staticItems['efMainHTML'], controller : 'MainCTRL' }) .when('/session/:id', {templateUrl : staticItems['efSessionHTML'], controller : 'SessionCTRL' })});
Request URL True File URLJS Controller
AngularJS App
Bootstrap-SF1
Salesforce1 Theme for Twitter Bootstrap CSS Framework
AngularJS App
Data AccessPeter : Getting data
Data Access for Salesforce1• Remote Object• @RemoteAction apex Methods• REST API for large requests
Data Access
AngularJS Services for Backend• Declare Service then Use Where Needed
Data Access
eventFlex.service('efSERVICES', function(){ return{ getAllEvents : function(callback){
...service logic... },
getSessions : function(callback){ ...service logic…
}...}
});
eventFlex.controller('MainCTRL', ['$scope','efSERVICES'...,funtion($scope,efSERVICES,...{
...controller logic...
};
Remote Object in Angular Service
<apex:remoteObjects > <apex:remoteObjectModel name="Event__c" jsShorthand="evt” fields="Name,Id,OwnerId,Short_description__c,..."/> <apex:remoteObjectModel name="Session__c" jsShorthand="session" fields="Name,Id,Location_text__c,Short_description__c,Description__c,..."/> </apex:remoteObjectModel></apex:remoteObjects>
getEventDetails : function(eventId, callback){ var data = new SObjectModel.evt(); var whereOb = { where : {Id : {eq:eventId}}};
data.retrieve(whereOb,function(err, records){ //if failure if(err) alert(err.message); else { console.debug(records); callback(records[0]); } }); },
Data Access
@RemoteAction in AngularJS Service
getMyFriendsAttendance : function(eventId, callback){ Visualforce.remoting.Manager.invokeAction( staticItems['getMyFriendsAttendance'], eventId, function(result, event){ if( event.status ) { callback(result); } }); },
Data Access
Components and CommunityAdrian : Power your productivity with the Angular Community
Angular Community and DirectivesThere is heaps of awesome open source out there
• Using other peoples components in your app :– Saves you loads of time– Is often better tested– Often more widely tested (cross browsers etc)
• It’s easy to search for components (directives) that will help you out.
• We used : – Angular Gantt (http://angular-gantt.github.io/angular-gantt)– Angular Charts (https://github.com/chinmaymk/angular-charts.git)
Front End
Installing Apps / DirectivesIntegrating other components
• Adding to your app is super easy :
1. Install
<apex:includeScript value="{!URLFOR($Resource.AngularD3, 'd3-master/d3.min.js')}"/>
<apex:includeScript value="{!URLFOR($Resource.AngularChartsJS)}" />
2. Inject
var d3App = angular.module('d3App', ['ngRoute', 'angularCharts']);
3. Add to controller
$scope.config = {}$scope.data = {}
4. Use Directive in Page<div ng-controller="d3CTRL"><div data-ac-chart="'pie'" data-ac-data="data" data-ac-config="config" class="chart"><div>
Front End
Building the PageAdrian : UI development
Understanding the Data Flow
VISUALFORCE
SERVICES
APEX Classes
CONTROLLER DIRECTIVES
The Execution Cycle
1. Page Loads2. Angular Controller calls init()3. Controller Calls the Services4. Services calls APEX classes via
@remoteAction5. Data Returned from Apex to
Services6. Services Returns data to
Controller7. Controller Refreshes the page8. VOLA!
Front End
MVC for Javascript. Remarkably similar to APEX.
public with sharing class efCharts {
public Id eventId {get;set;}public list<events> evtList {get;set;}
public pageReference getNewDashboard(){return null;
}}
d3App.controller('d3CTRL', function($scope, chartServices, $routeParams) { $scope.eventId = $routeParams.id;
$scope.events = [];
$scope.refreshData = function(){...
}}
<apex:page controller="efCharts" ><apex:repeat value=”{!evtlist}” var=”e”>{!e.Name}
</apex:repeat></apex:page>
<div ng-app="d3App"><div ng-controller="d3CTRL">
<ul ng-repeat=”e in events”><li>{{e.Name}}</li>
</ul></div>
</div>
APEX Controller Angular Controller
Visualforce Page HTML Page
Front End
Bindings - putting stuff on the page• Output bindings are the simplest way to stamp data on your page using {{}}
<span>{{Event.Start_Date__c}}</span>
• However this prints out the wrong format so lets use a formatter. Magic.<span>{{Event.Start_Date__c | date : ‘dd-MM-yyyy’}}</span>
[Works for Date, Number, Currency, Uppercase, Lowercase]
• If we want a 2 way connection e.g. an input field we use ng-model which will refresh the page on change of this value. Amazing for live filtering.
<input ng-model=”searchText”/>
Front End
Repeats, Repeats, Repeats• Repeats are key to delivering lists of data. They can be either Arrays OR Objects.
<li ng-repeat=”item in items”>{{item.Name}}</li>
<li ng-repeat=”(key, value) in items”>{{value.Name}}</li>
• Angular Packs some serious punch with filters–Simple filter that searches for anything in the array <li ng-repeat=”item in items | filter: searchText”>{{item.Name}}</li>
–Restricted filter that searches for a field on an object<li ng-repeat=”item in items | filter: {name:searchText}”>{{item.Name}}</li>
–Add in orderBy for maximum control<li ng-repeat=”item in items | filter: searchText | orderBy:’Name’”>{{item.Name}}</li>
Front End
Directives & Partials• Directives are tags that allow you to create angular components. Directives can be reused thought out your app.
• You need to specify how you want to register a directive Attribute or Tag:<span my-directive=””></span> or <my-directive></my-directive>
• Key components of a directive include : –HTML template / Partial : specify how you want to display data–Scope : Specify which pieces of data you need–Link Function : specify how you want to interact with the component.
• On your page now simply reference the directive and pass in the data<span my-directive=”” data-item=”dataitem”></span>
Front End
An Example1. Use Attribute to get directive &
replace original tag
2. Allow dataItem to be passed in. NOTE you use data-item=”” in the HTML.
3. Template as HTML
4. Create a link function with new scope and allow access to the HTML element and attributes. Great for adding on-click events, jquery etc
Front End
myapp.directive(‘myDirective’, function() {return {
restrict: 'A',replace: true,scope: {
dataItem:’=’ },
template: '<span>{{dataItem.name}}</span>',
link: function (scope, element, attr){scope.dataitem2 = ‘ABCD’
scope.resetValue = function(){scope.dataItem = scope.dataitem2
}
element.bind(‘click’, scope.resetValue);
}
};
So the app in the end...Adrian : Recap
EventFlex as a SolutionMapping the features to the UI
Twitter Integration
Chatter
Service Cloud
Communities
Salesforce1
Force.com
Questions?