SugarCRM - Javascript Snippets - Part 1

Part #1 of the Javascript snippets series covers the App object - and it's common use cases.

SugarCRM - Javascript Snippets - Part 1

SugarCRM uses backbone.js and Handlebars to display the User Interface - which makes it really simple and easy to use. But often there is a need to interact with existing SugarCRM components such as Drawers and Contexts. Below are frequently used SugarCRM Javascript snippets for your reference.

App Object

Any interaction with SugarCRM application can be done with the app object, which is available by default in components. For running the examples in console, you can also use the global App object (in upper case).

The App object virtually gives you access to the entire User Interface classes and objects. Some of the examples are:

  • app.api - call backend APIs
  • app.drawer - interact with Drawer
  • app.config - access configuration variables
  • app.user - current user
  • app.controller - main UI controller
  • app.alert - display/dismiss alerts
  • app.acl - access control actions
  • app.data - to create beans and collections
  • app.router - to navigate the app
  • app.lang - to access language/dropdowns
  • app.utils - utility methods
  • app.bwc - used to access legacy Sugar 6 functionalities.

API

The app.api object provides easy to use methods to call backend API, and abstracts passing auth token/error handling. It is in essense an upgraded HTTP wrapper for Sugar API calls.

CRUD

To get a record from the backend, use app.api.call('read'):

var url = App.api.buildURL('Accounts', null , {id: "ACCOUNT_ID"});
// Generates "rest/v11_5/Accounts/ACCOUNT_ID"

App.api.call('read', url, null, {
    success: function(result) {},
    error: function(result) {},
    complete: function(result) {}
});

There are three types of callbacks - success, error - as you know. But there is also a complete callback, that is called after both success/error, in case you want some catch all scenario like closing an alert, etc.

The first argument read is just an equivalent of HTTP GET.  update relates to HTTP PUT, while create relates as HTTP POST.

You can also fetch only specific fields, and even filter records, for example:

// Simple filter to query 
var filter =  { "filter": [
    {
      "account_type": "Partner"
    }
  ]
};

// Just an example of passing Query String parameters
var params = {
    fields: "id,name",
    max_num: 5
}

// Generate the URL
var url = App.api.buildURL('Accounts', 'filter', null, params);
// Generates "rest/v11_5/Accounts/filter?fields=id,name&max_num=5"

// Call the POST method with filter
App.api.call('create', url, filter, {
    complete: function(result) {}
});

Note: The third argument in app.api.call is treated as the POST/PUT content.

To update a record, for example, you can try something like:

url = App.api.buildURL('Cases', null, {id: "CASE_ID"});
attributes = {status: "Resolved"};

App.api.call('update', url, attributes, {complete: callback});

File Handling

There are more in-depth use cases, and you can pretty much do anything from basic GET calls to even File uploads and downloads!

Here is an example of file upload done through API:

var url = App.api.buildURL("Accounts", 'export', {id: "ID"}, params);

App.api.fileDownload(url, {}, { iframe: this.$el });

File download creates an iframe in the current div to trigger the download, which is why you have to provide the iframe parent location as a parameter.

More details on file handling and advanced API concepts is coming up in a future post! Stay Tuned!

Legacy UI

In order to access Legacy Sugar 6 UI from the Sugar 7+ UI, there is a special step that you need to perform - which is where app.bwc comes into picture.

The way login works in Legacy UI vs Sugar 7+ UI is different - so in order to navigate from 7+ to 6 for the first time, you have to call the app.bwc.login - if not, the navigation or functionality just won't work.

Eg: To open a report from Sugar 7 UI, use this:

App.bwc.login(null, _.bind(function() {
    this._triggerDownload(this._buildDownloadLink(templateId));
}, this));

This functionality will be phased out eventually once Sugar decommissions legacy UI but useful for folks still in Sugar 7/8.

Note: To know the complete API cheatsheet and Rest client files, visit our blog - SugarCRM API CheatSheet

Alerts

Display simple alerts using app.alert:

App.alert.show('alert-id', {
    level: 'success',
    title: 'Hello',
    message: 'Display Successful!',
    autoClose: true,
    autoCloseDelay: 1000
});
Alert levels can also be info, error, warn, confirmation, and process - process used for showing a loading message

Dismiss alerts using App.alert.dismiss(id) or App.alert.dismissAll

Router

Tip: Want a quick and easy way to refresh your screen without reloading the page?  try App.router.refresh();

Use router to navigate to a specific URL. You can create URLs using the buildRoute utility method:

var route = App.router.buildRoute("Accounts"); // route = "#Accounts"
App.router.navigate(route, {trigger: true, replace: true});

You can pass optional arguments - trigger - initiates callback function for route, if any.  and replace- doesn't add to browser history..

To navigate to a record, you can use buildRoute with the second argument as id:

App.router.buildRoute("Accounts", "ACCOUNT_ID", "edit");

Config

The application config can be accessed using app.config - this is really useful if you want to access dynamic parameters that could be defined in config_override.php

To define a config to be used in the frontend, define it as:

$sugar_config['additional_js_config']['jira_url'] = 'http://jira.seventunes.com/';

It can then be used in the UI as app.config.jira_url

Did you know? Javascript config is stored in cache/config.js

User

To access user related information, you can use app.user. Eg: App.user.get("id")

This is especially useful to get user preferences, for example, the timezone and email client preferences. Eg:

App.user.getPreference("timezone");
// "America/New_York"

Language / Dropdowns

To access the language files and dropdowns, use the app.lang object.

Get the label for a module:

App.lang.get("LABEL_NAME", "Accounts");

Get all dropdown values by name:

App.lang.getAppListStrings("account_type_dom");

Utils

There are some helpful app.utils methods - here are some examples:

  1. Clone an entire object: app.utils.deepCopy(source)
  2. Validate Email: app.utils.isValidEmailAddress(str)
  3. Capitalize Name: app.utils.capitalize(name)
  4. Format Number: app.utils.formatNumber(value, round, precision, etc.)
  5. Generate UUID: app.utils.generateUUID()
  6. Compare two beans: app.utils.compareBeans(beanA, beanB)

Access Control

ACL is useful if you are dynamically generating buttons/methods and would like to check if the user really has access to a functionality.

Eg: To find if a user has access to edit a field on a model, you can use:

App.acl.hasAccessToModel("edit", model, "restrictedFieldName");

You can also check if a user has access to a particular module itself (field name is optional)

App.acl.hasAccess("create", "Accounts", {"field": "name"});

Drawer

SugarCRM often uses Drawer to display popup-like behavior and we like it! The way it works is by

SugarCRM App Drawer

Drawers are just wrappers around layouts. In order to open a drawer, you have to specify a layout.

For example, here is how the "Create" popup works:

App.drawer.open({
    layout: 'create',
    context: {
        create: true,
        module: 'Contacts'
    }
}, function(context, model) {
    if (!model) {
        // User clicked on cancel
        return;
    }
});

To close a drawer, you can use:

App.drawer.close();

To get the active drawer, you can use:

App.drawer.getActive();

Controller

app.controller is the page controller and should be used carefully. I use it only for debugging, for example, to get the current page's model in JS Console, using:

App.controller.context.get("model").attributes

This will return the current record view's model.

Models / Collections

Models and Collections are basically Backbone.js objects. In a view/layout, you can access the model using this.model or this.collection.  More details to follow soon.


In this Part #1 blog, we've covered the common uses cases of SugarCRM App object. Stay tuned for our #2 blog which will cover Views, Layouts and other complex functionalities!

More SugarCRM articles: