11

I have just recently started building Lightning Applications, and I do not understand why there are two Javascript components in each bundle. What is the difference between the controller and the helper? How do I know what code to put where?

7

In addition to what everyone else has said...

The helper is designed to have shared code in it. So, you could have code shared by your renderer and your controller or by multiple controller functions. That should go in the helper JS file.

I think that a good practice is to let the controller respond to events, possibly perform some amount of control flow, and delegate business logic to the helper as a separation of concerns. It also sets you up to be able to reuse your business logic in other parts of the component in the future.

Helper code can be shared among components when they are related through inheritance. If one component extends another it inherits its super component's helper and can override it.

Sub components can call super component controller methods, but that may be deprecated in the future according to the documentation in the Lightning Components Developer's Guide.

Components can communicate with each other via events to "share" code. For example, if you have a component that handles writing business logic errors in a uniform way in your app, and handles some sort of error related event, you could fire an event to trigger it to handle an error.

| improve this answer | |
4

If you are more the visual type of person. Follow this link from Salesforce Developer's Blog: Understanding JavaScript Controllers Versus Helpers In Lightning Components
Here's what's under this link:

By Raja Rao DV | Published: June 15, 2015
JavaScript Controllers and Helpers play a key role in Lightning Components Framework. One of the first things people new to the framework wonder is: What exactly is the difference between JavaScript Controllers and JavaScript Helpers. So let’s go over the differences between them.

To understand it better, let’s say we have an Account list that shows two Account components (Account.cmp). It may look like this:

<c:AccountList>
   <c:AccountCmp id=”1” />
   <c:AccountCmp id=”2” />
</c:AccountList>

Visually, the Account list looks like the 1st picture below. But while running, it actually looks something like the 2nd picture:
Diff controller helper

Each Account Component component (bundle) is made up of a markup, JavaScript controller, a Helper, a Renderer and more.

But, while running, the framework creates an instance of the Controller, an instance of the Renderer for each component but creates only one copy of the Helper and passes the reference of the Helper into every Controller instance and every Renderer instance.

In our example with two Account components, the framework creates one copy of the Helper and passes the reference of this Helper into two controller and to two renderer instances.

Benefits:

  • Since Helper is shared across everything, it allows us to share and keep logic across of Controllers and Renderers in one place.
  • It also helps us keep logic within Controllers and Renderers lean.

So we should try to delegate business logic to Helpers whenever possible.

For example:
Instead of:

// controller.js
callServer: function(cmp, helper) {
   var action = cmp.get("c.getAccounts");
   $A.enqueueAction(action);
}

// renderer.js
afterRender: function(cmp, helper) {
   this.superAfterRender();
   var action = cmp.get("c.getAccounts"); 
   $A.enqueueAction(action); 
}

Do The Following:

// controller.js
callServer: function(cmp, helper) {
  helper.callServer();
}

//helper.js (shared across all instances of controllers and renderers)
callServer: function(cmp, helper) {
   var action = cmp.get("c.getAccounts");
   $A.enqueueAction(action);
}

// renderer.js
afterRender: function(cmp, helper) {
   this.superAfterRender();
   helper.callServer();
}

Note: If there are multiple types of components (say, AccountItem.cmp and AccountDetails.cmp), each component type will get a helper of their own.

When To Use Controllers v/s Helpers:

  1. Use Controllers to listen to user events and other events like component, application events. But delegate business logic to helper.

  2. Do similar delegation in all Renderer functions (render, rerender and so on).

  3. Anytime you need to call one controller function from another controller function, move that logic to Helper.

Anti-Pattern(s):
Too many functions in the Helper: If you get into this situation, it’s time to refactor the component itself into smaller sub components.

| improve this answer | |
  • If the link answers the question, can you reference it here or provide a synopsis? Links can break over time, making link only answers less valuable on the whole. Ideally your answer should still hold up even if the link breaks. – Adrian Larson Dec 12 '16 at 21:55
  • 1
    Of course I can do that! – Hugues Lavoie Dec 12 '16 at 22:28
1

A controller contains functions to handle events in the component.

A helper contains utility functions that can be reused in the component bundle; for example, by a controller and a renderer.

You don't have to use a helper but it can be helpful (pardon the pun) for reuse. It also keeps a better interface in the controller in that each function in the controller can be called by {!c.controllerFn} in the markup. You probably don't want markup calling {!c.utilityFn} so you can stick utilityFn in the helper instead.

More comparison with deeper links at https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_bundle.htm

| improve this answer | |
  • 1
    So I am able to bind one helper to multiple controllers? Is that how it helps with reuse? How would I do that? Perhaps a separate question is in order there. – Adrian Larson Feb 27 '15 at 4:56
  • That's a great separate question, @AdrianLarson! – Marty C. Feb 27 '15 at 12:10
1

Every component ,if you have client side logic or a server call ,you will put all in the client side controller .

To help our code to modularize ,every bundle is provided with the helper .

Helper functions are local to a component, improves code reuse, and moves the heavy lifting of JavaScript logic away from the client-side controller where possible. The following code shows the helper function, which takes in the value parameter set in the controller via the item argument. The code walks through calling a server-side action and returning a callback but you can do something else in the helper function.

Example on how to use this

({
    newItemEvent: function(component, event, helper) {
    helper.updateItem(component, event.getParam("item"));
   }
})

My helper function will be as below

({
updateItem : function(component, item, callback) {
    //Update the items via a server-side action
    var action = component.get("c.saveItem");
    action.setParams({"item" : item});
    //Set any optional callback and enqueue the action
    if (callback) {
        action.setCallback(this, callback);
    }
    $A.enqueueAction(action);
  }
})

Using my helper function as you can see I can use this to send different parameters .It is very similar to utility method concept in APEX where we can reuse the method .It helps to keep code modular .

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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