Getting Sassy! Namespacing Bootstrap

Bootstrap is the most popular front-end web design framework and is usually my go to when I want to quickly create a user interface that is visually appealing and mobile friendly. I'll be the first to admit that I am not that great at design (just look at this blog!), so frameworks like Bootstrap are a godsend. Using Bootstrap with Salesforce (at least the classic view) can be a huge pain because of the conflicting stylesheets from the sidebar and header:

Conflicting Styles

This isn't the case in Salesforce Lightning, but there are plenty of organizations that are not ready for the transition to the new interface. I knew that the answer to this problem was just to namespace the Bootstrap, but the execution involved running commands with Ruby, Sass, and Node, which for a while was just non-Salesforce magic that I dared not touch. For a few years I just avoided using Bootstrap in Salesforce, opting to just style everything myself. If you've ever felt this way, then this post is the hand holding you might be looking for.

TL;DR

If you really don't want to do this, here's the namespaced CSS that you can just include in your project now: https://gist.github.com/seanpat09/6207236541d701da40ce

It doesn't include the glyphicon fonts, but pretty much everything else is there.

Namespacing Bootstrap

(This is mainly for Mac users. Linux will largely be the same. Sorry Windows users)

Run all these commands in Terminal

Install the dependencies on your machine

1. Make sure you have Ruby installed

Ruby comes pre-installed on Macs, but here's how you check for sure:

Your-Macintosh:~ seancuevo$ ruby -v
ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin14]

If somehow you see something like this:

Your-Macintosh:~ seancuevo$ ruby -v
-bash: ruby: command not found

Then you need to install Ruby

2. Install Sass

gem install sass

If you see any errors, trying running this:

sudo gem install sass

3. Install nvm

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash

4. Install node.js using nvm

nvm install 5.0

You can use node in your terminal session with:

nvm use 5.0

You now have all the tools necessary to namespace Bootstrap!

Compile a namespaced version of Bootstrap

You can run the following commands from whatever directory you want, but just make sure to stay in that directory as all the files will be written to the directory and all of the commands will be relative to it.

1. Start node:

nvm use 5.0

2. Install Bootstrap-sass

npm install bootstrap-sass

This creates a folder called node_modules in your current directory. This contains files necessary to compile bootstrap

3. Create the .scss file

In the same directory, create a file called sfdcBootstrap.scss with the following contents

.sfdcBootstrap{
$icon-font-path: "fonts/bootstrap/";
@import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";
}

This will create the bootstrap css file where only styles that descend from the .sfdcBootstrap class are affected by Bootstrap. You can name the class whatever you want, just make sure to change it in the .scss file.

4. Compile your css file with Sass

In the same directory, run this command in Terminal:

sass sfdcBootstrap.scss sfdcBootstrap.css

You should now have a file called sfdcBootstrap.css in your directory.

5. Build your static resource

Run this command to open your current directory in Finder:

open .
  • In Finder, create another folder and put the sfdcBootstrap.css in it.
  • In the node_modules folder, navigate to bootstrap-sass > assets.
  • Copy the fonts folder and place that in the same folder as sfdcBoostrap.css.
  • Select both sfdcBoostrap.css and the fonts folder, right click and select Compress 2 Items
  • Rename the resulting archive file to sfdcBootstrap and upload to Salesforce as a static resource.

Use your namespaced bootstrap in your Visual Force Page

Here is a sample Visual Force page using the resource:

<apex:page showHeader="true" sidebar="true">
<apex:stylesheet value="{!URLFOR($Resource.sfdcBootstrap, 'sfdcBootstrap.css')}" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<div class="sfdcBootstrap">
Formatted with bootstrap!
</div
Not formatted with bootstrap!
</apex:page>

Everything outside of the sfdcBootstrap div (which includes the sidebar and header) will NOT be formatted with Bootstrap

Namespaced Bootstrap

Git 'Er Done: Adding Git to Your Salesforce Development Process

Version control is a crucial component of any development process and even more so if you are working in a team. It is so important that I will refuse to work on any project before implementing some kind of version control system even if it means I have to maintain it on my own. Not only has it saved my ass countless times, it also facilitates and speeds up collaboration for development teams.

Git is my preferred version control system and after reading this post you will learn:

  • How to get your Salesforce code set up in Git
  • How to utilize version control in your development workflow

Getting your Salesforce code on to Git

If you don’t have Git set up on your machine, check out these two links first:

https://git-scm.com/book/en/v2/Getting-Started-Installing-Git

https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup

Next pull down the metadata that you want to track from your Salesforce production org using whichever method you prefer (Mavensmate, Eclipse, Ant, etc). We’re using pulling the code from production because it is the source of truth of your org. Even if your sandbox has new changes in it, it can be refreshed at any time or never merged into production. Production always takes precedent.

If you’re not sure which metadata types you should pull down, I recommend this package.xml file as a default:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>ApexClass</name>
</types>
<types>
<members>*</members>
<name>ApexComponent</name>
</types>
<types>
<members>*</members>
<name>ApexPage</name>
</types>
<types>
<members>*</members>
<name>ApexTrigger</name>
</types>
<types>
<members>*</members>
<name>StaticResource</name>
</types>
<version>34.0</version>
</Package>

Developers will be working with these metadata types for a majority of their time and thus these will benefit from version control the most.

Once you’ve pull down your metadata open up Terminal (or Git Bash if you’re using Windows) and navigate to the root folder of your project. This is typically the folder that holds your src folder. Run these commands to create your git repository:

//creates the repo
git init

//adds everything in the folder to the repo
git add .

//commits code to your repo. You can change the message to whatever you want,
//but this is what I usually put
git commit -m "current state of production code"

And you’re done! Adding your git repository to a remote location is out of scope for this blog post, but I suggest using one of the following:
BitBucket - Better for consultants because the pricing model is to pay per collaborator with unlimited private repositories
GitHub - Better for product developers or those working in industry as you pay per private repo with unlimited collaborators.

Adding Version Control to Your Development Workflow

Here’s a really basic development workflow for any new feature you are working on:

  1. Create a branch off of the master branch (typically named after the feature or story number)
  2. Make a change in the code that you can describe in one sentence without using the word “and” (e.g. ‘Stubbed out controller tests’)
  3. Commit the change to your branch
  4. Repeat steps 2 and 3 until the feature is completed (which includes testing)
  5. Merge into the master branch
  6. Deploy the master branch to your Production org.

Let’s break down each of these steps into more detail:

1. Create a branch off of the master branch (typically named after the feature or story number)

First, create or refresh a sandbox for you to develop in. You want your development org to mirror your production org as much as possible so that you know that the features you are building will integrate smoothly with what’s currently in production. In Terminal, create a branch off of the master branch with the following commands:

//Make sure you are actually in the master branch
git checkout master

//Create a new branch and put yourself in it at the same time. myBranch can be named whatever you want.
//I usually name it after the feature you are building, or use the story number if you're doing agile
git checkout -b myBranch

In your IDE, make sure you are saving files to your sandbox org, not production. You’re now ready to start developing!

2. Make a change in the code that you can describe in one sentence without using the word “and”

Commits should be small and descriptive. This makes tracking history, comparing file differences, and reverting code much easier. It’s easier to make sense of a bunch of small changes instead of one giant change. Also, if your history is a series of steps you have the flexibility of reverting only certain changes instead of all or nothing.

3. Commit the change to your branch

After you make a (small) change, do the following in Terminal: (I’ve included the outputs so you know what to expect)

//add the file(s) you changed to git. You can also do git add .
//but I prefer to be explicit
My-Computer:myProject thisIsMe$ git add src/classes/ContactController.cls

//View the changes you staged. Not necessary but I do it to make sure
//I only add what I expected to add
My-Computer:myProject thisIsMe$ git status
On branch newFeature
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)

modified: src/classes/ContactController.cls

//Commit the change to Git
My-Computer:myProject thisIsMe$ git commit -m 'my change'
[newFeature bae2c2d] my change
1 file changed, 1 insertion(+), 1 deletion(-)

4. Repeat steps 2 and 3 until the feature is completed (which includes testing)

Continue to make small changes until you are ready to call the feature complete. This includes any unit testing you need to do as well as any QA/UAT.

5. Merge into the master branch

When you are done, it’s time to merge it to the master branch:

//Checkout the branch you are merging into
git checkout master

//Merge the branch with the feature you've been working on
git merge myChange

6. Deploy the master branch to your Production org.

Once it is merged into the master branch, go ahead and deploy the code to your production org using whichever method your prefer (your IDE, change set, ant).

Why create a new branch? Why not just work in master?

Working in branches gives you more flexibility and facilitates working on separate features simultaneously. Take the following example:

You are tasked with adding a new feature:

git checkout master
git checkout -b newFeature

While you are creating that new feature, the business says there’s a bug in production that needs to be fixed quickly. So you do the following:

//Get back into the master branch, which does not include any code from the new feature
git checkout master

//Create a new branch for your hot fix.
git checkout -b hotFix

Once you complete the hot fix and merge it into your master branch (and then production org), you can just return to work on your new feature as if nothing happened. You don’t have to manually remove or add code; Git did it all for you. If you want, you can also merge the hot fix into your newFeature branch so that your branch is caught up with master.

git checkout newFeature
git merge hotFix

New Possibilities

While version adds some overhead to development process, it also helps you become more productive. Having a history will make debugging issues easier as you’ll have a trail of what changed in the code when the bug arose. You’ll also feel more empowered to make changes in the code because if something goes wrong you always have something to revert back to.

Version control also opens the door to new opportunities. In the next post, we’ll cover how to use Git to automate deployments and manage collaboration between several developers.

Remote Actions By Any Other Name (Extra Credit: local development?)

While working on a managed package with several developers, dealing with the namespace can be really annoying. Developers (ideally) would not be developing directly in the packaging org, so your team won't have access to the namespace and they'll find themselves trying to figure out how to program more dynamically without hard references to the namespace. This sounds like a good thing, but in practice it can lead to some poor implementation choices, especially when working with Javascript and Remote Actions.

Flawed Dynamic Namespacing

Salesforce recommends using the {!$RemoteAction} merge field to deal with namespacing. For example, your code might look like this:

    Visualforce.remoting.Manager.invokeAction(
'{!$RemoteAction.MyController.doTheThing}',
function(result, event) {
if (event.status) {
handleSuccess();
} else {
handleRejection(event);
}
}
);

This works great because you don't have to worry about the namespace at all. This code will work in your separate developer org as well as the packaging org. However, since static resources don't support merge fields this has to be done within the Visual Force page inside a script block. It's not a huge deal, but you do lose the benefit of the static resources caching plus it makes your Visual Force page messier.

Stick it in an object

Instead just stick your namespaced controller in another variable:

(function(){
'use strict';
var SFDCCtrl = MyNamespace ? MyNamespace.myController : myController

function myRemoteCall(){
SFDCCtrl.doTheThing( function(result, event){
if (event.status) {
handleSuccess();
} else {
handleRejection(event);
}
});
}
}());

In your Visual Force page Salesforce creates global object named after your controller that contains all of your remote actions. If that controller is namespaced, it just wraps that object in an object named after your namespace:

//Namespaced Controller
var MyNamespace = {
MyController : {
doTheThing : function(){};
}
}

//Non-namespaced controller
var MyController = {
doTheThing : function(){};
}

Now you can stick your javascript in a static resource without having to worry about it working in namespace and non-namespaced orgs.

Extra Credit: Possible Local Development?

Local development is like the holy grail of Salesforce programming. I don't think we'll ever have full-fledged local development, but when it comes to building Javascript heavy pages there might be some hope. Here's how I would do the namespacing with Angular:

//SFDCCtrl.js
(function () {
'use strict';
angular.module('myModule')
.service('SFDCCtrl', SFDCCtrl );
function SFDCCtrl(){
this.MyController = MyNamespace ? MyNamespace.MyController : MyController;
}
})();
//AController.js
(function () {
'use strict';
angular.module('myModule')
.controller('AController', AController );
AController.$inject = ['SFDCCtrl'];
function AController(SFDCCtrl){
function myRemoteCall(){
SFDCCtrl.MyController.doTheThing( function(result, event){
if (event.status) {
$scope.theThing = result;
} else {
handleRejection(event);
}
});
}
}
})();

With the angular example, since your controller is tucked away nicely in its own service, you easily mock your SFDC controller with your tests. But why stop there? Why not mock it for development so you can work locally? With Javascript frameworks like Angular and React, I find myself using less Visual Force, simply using the controller for interactions with the database. This can be frustrating because you know that a majority of your page could be compiled on your machine, but you have to hit the server on every save, which can take several minutes for each request! Take the following super simple example that uses the above angular example:

//MyPage.page
<apex:page controller="MyController" applyBodyTag="false">
<body app="myModule">
<div ng-controller="AController">
{{theThing}}
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<script src="{!URLFOR($Resource.myAngularApp,'SFDCCtrl.js')}"/>
<script src="{!URLFOR($Resource.myAngularApp,'AController.js')}"/>
</apex:page>

This is basically just a regular html/js page wrapped in visualforce (with a few merge field changes):

<html>
<body app="myModule">
<div ng-controller="AController">
{{theThing}}
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<script src="SFDCCtrl.js'"/>
<script src="AController.js'"/>
</html>

Now let's replace the script containing salesforce controller object and replace it with a mock file:

<html>
<body app="myModule">
<div ng-controller="AController">
{{theThing}}
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<script src="SFDCCtrlMOCK.js'"/>
<script src="AController.js'"/>
</html>
//SFDCCtrlMOCK.js
(function () {
'use strict';
angular.module('myModule')
.service('SFDCCtrl', SFDCCtrl );
function SFDCCtrl(){
this.MyController = {
doTheThing : doTheThing
}

function doTheThing(){
//return a mock of whatever you expected Salesforce to return you
return 'Athing';
}
}
})();

The Salesforce controller is just an interface now that you or someone else can work on separately from the front end. Now you can work on your page locally! Maintaining these mocks might seem like extra work, but you should probably be building these mocks anyway for Javascript unit testing purposes. Also, the time you save not having to deploy to the server every time you save might even outweigh the cost of building the mock files.