Zengine Services

Zengine provides several services for you to inject as dependencies when developing your plugin.

znMessage

A service that displays a temporary alert message at the top of the page.

znMessage(message, [type], [duration])

// Example controller including the 'znMessage' service.
plugin.controller('MyCntl', ['$scope', 'znMessage', function($scope, znMessage) {
    $scope.onSubmit = function() {
        znMessage('Your data was saved!', 'saved');
    };
}]);
Param Type Details
message string The message to display.
type (optional) string Determines the background color of the message. Valid types: 'info', 'saved', 'error', 'warning'. Default is 'info'.
duration (optional) integer How long the message is displayed in milliseconds. Default is 4000.

Forces any open messages to close.

znMessage(false);

znConfirm

A service that displays a confirmation dialog.

znConfirm(message, [callback])

var close = function() {
    console.log('Closed');
};
znConfirm('Are you sure you want to close?', close);
Param Type Details
message string The message to display in the dialog.
callback (optional) function If defined, will add a 'Yes' button to the dialog, which when clicked, will execute the callback.

znModal

A service that displays a modal dialog. For an alternative modal service, try Angular bootstrap’s $modal.

znModal(options)

plugin.controller('myMainCntl', ['$scope', 'znModal', function($scope, znModal) {
    $scope.onSubmit = function() {
        znModal({
            title: 'My Modal Dialog',
            template: "<form ng-controller='myModalCntl' name='myForm'><input name='input' required></form>",
            classes: 'my-dialog',
            btns: {
                'Save': {
                    primary: true,
                    action: function(scope) {
                        // on Save click
                    }
                },
                'Delete': {
                    danger: true,
                    action: function() {
                        // on Delete click
                    }
                }
            }
        });
    };
}]);
/*
 * For enhanced control over modal buttons
*/
plugin.controller('myModalCntl', ['$scope', function($scope) {
    $scope.setBtnAction('Save', function (callback) {

        // See https://code.angularjs.org/1.2.21/docs/api/ng/directive/form for more details
        var form = $scope.myForm; // value of the name attribute on the form.

        if (!form.$valid) { // e.g. empty input
            return false; // do nothing
        }

        var keepOpen = false; // close the modal afterwards
        callback($scope, keepOpen); // call the original callback with $scope passed to it
    });
}]);
Param Type Details
options Object

The object has the following properties:

  • title - {string} - The dialog title.
  • template - {string} - Raw HTML to display as the dialog body.
  • templateUrl - {string} - Takes precedence over the template property. Works the same as the 'templateUrl' option when registering a directive. Corresponds to the id of the script tag that wraps the HTML to display as the dialog body. For more info, see the Angular docs on the script directive.
  • classes - {string} - One or more (space-separated) CSS classes to add to the dialog.
  • closeButton - {boolean} - A close button is included by default. Passing false won't include it.
  • unique - {boolean|string} - Whether to close any other open dialogs. true means close any other dialogs. Alternatively, a CSS class name can be passed to close related dialogs. If you are using the plugin location zn-plugin-form-top, in order for the modal to work this must be set to true.
  • btns - {Object} - An object hash of buttons to include. Each button is a key-value pair, where the key is name used for the button text, and the value is a hash object that can include the following properties:
    • one of three possible keys to determine background color: success, danger, or primary.
    • action callback to run when the button is clicked. By default, the action callback is called with no arguments, but this can be enhanced by calling the function setBtnAction(name, onClick), which is available on the modal scope (more detail on modal scope below). The first argument, name, is the name of the button specified as the key in the btns hash. The second argument, onClick, is a function that is called on click of the button, instead of the original callback. When called, onClick is passed a wrapper function that takes two arguments: data and keepOpen. When the wrapper function is called within the onClick function, it calls the original actioncallback with its first argument data, and unless keepOpen is true, closes the modal.
  • scope - {Object} - This property determines which scope to use in the modal template. (If you are familiar with Angular, this property is similar to how the scope property works with a directive.) There are three options for the scope to be used:
    • By default, the modal creates a child scope, which prototypically inherits from the $rootScope.
    • To create a child scope, which prototypically inherits from a different parent (i.e. the scope where the modal is being used), you can pass a reference like this: scope: $scope.
    • To create an isolated scope, which does not prototypically inherit, so that it is completely isolated from its parent, you can pass an object like this: scope: { ... } .
    In addition the scope associated with modal's content is augmented with the method setBtnAction(name, onClick).

znFiltersPanel

znFiltersPanel is a service that allows you to view and build a data filter by opening a modal. This is different from the znInlineFilter directive, which displays the filter builder directly in the page. The filter returned from the panel can be used to query records, save to a data view, and build and run calculations.

znFiltersPanel.open(options)

plugin.controller('myMainCntl', ['$scope', 'znFiltersPanel', 'znData', function($scope, znFiltersPanel, znData) {

    $scope.formId = 123;

    $scope.openFiltersPanel = function() {

        znFiltersPanel.open({
            formId: formId,
            filter: {
                and: [{
                    prefix: '',
                    attribute: 'folder.id',
                    value: 0
                }]
            },
            onSave: function(filter) {
                // use filter to interact with API, e.g. query records

                znData('FormRecords').get(
                    {
                        formId: $scope.formId,
                        filter: JSON.stringify(filter)
                    }
                );
            },
            fieldTypeBlacklist: ['text-input', 'linked'],
            attributeBlacklist: ['field123', 'createdByUser.id']
        });
    };
}]);
Param Type Details
options Object

The object has the following properties:

  • formId - {integer} - Form ID of the form you want to filter on.
  • filter - {Object} - Existing filter to open with the panel. Does not apply to znInlineFilter directive.
  • onSave - {function(filter)} - A callback executed when the filter panel is saved. Does not apply to znInlineFilter directive.
  • subfilters - {boolean} - Whether to allow subfiltering on related fields. Defaults to true.
  • groups - {boolean} - Whether to allow nested conditions. Defaults to true.
  • dynamicValues - {boolean} - Whether to allow dynamic values such as logged-in-user. Defaults to true.
  • operators - {array} - A list of operators to allow filtering on. Defaults to ['and', 'or'] but ['and'] or ['or'] can also be passed.
  • attributeBlacklist - {array} - A list of specific fields to prevent the user from filtering on. The list can contain an attribute like 'field123', where 123 is the ID of a field belonging to the form. The list can also contain the following attributes: 'folder.id', 'createdByUser.id', 'created', and 'modified'.
  • prefixBlacklist - {array} - A list of prefixes to prevent the user from filtering on. The following is a list of valid prefixes:
    • ""
    • "not"
    • "contains"
    • "not-contains"
    • "starts-with"
    • "ends-with"
    • "min"
    • "max"
    • "not-validates"
  • fieldTypeBlacklist - {array} - A list of field types to prevent the user from filtering on. The following is a list of valid field types:
    • calculated-field
    • checkbox
    • country-select
    • date-picker
    • dropdown
    • file-upload
    • heading
    • hidden-field
    • html
    • link-counter
    • linked
    • member
    • numeric
    • page-break
    • radio
    • spacer
    • state-select
    • summary
    • text
    • text-area
    • text-input
    • year
    For a more complete reference, see the API documention on form field taxonomy.

znFilterMatcher

The znFilterMatcher service lets your plugin compare a record against a filter and determine if it’s a match. It uses the same matching as querying records using a filter or for conditional field rules. One case you might use this for is to filter down a list of records that have already been fetched without making an additional request to the API.

For the matching to work properly, the data you are filtering on must be present in the record. Additionally, subfilters of fields on other forms and dynamic conditions, such as logged-in-user, are not supported.

var record = { 'field123': 'Chicago', 'field456': 2015 };

if (znFilterMatcher(record, { 'and': [{ 'prefix': '', 'attribute': 'field123', 'value': 'Chicago'}]})) {
	// Record Matches field123 = Chicago
}

if (znFilterMatcher(record, { 'and': [{ 'prefix': 'min', 'attribute': 'field456', 'value': 2015}]})) {
	// Record Matches field456 >= 2015
}

znData

The znData service provides a collection of resources that should be used for accessing data via the Zengine REST API. After passing the name of the resource to the service, you get back an object that can use the methods described below: get, query, save, update, delete, saveAll, updateAll and deleteAll. All methods return a standard Angular promise object.

znData(resourceName).get(params, successCallback, errorCallback)

Performs a GET request on a single object. The id param, if passed to params, will be interpreted as a url parameter.

// Get single workspace member
// equivalent to: GET /workspaces/123/members/456
// response will be a JSON Object
znData('WorkspaceMembers').get({ workspaceId:123, id:456 }, function(member) {
    $scope.member = member;
});

znData(resourceName).query(params, successCallback, errorCallback)

Performs a GET request on an array of objects. The id param, if passed to params, will be interpreted as a query parameter.

// Get list of workspace members
// equivalent to: GET /workspaces/123/members?id=456
// response will be an array
znData('WorkspaceMembers').query({ workspaceId:123, id: 456 }, function(members) {
    $scope.member = members[0];
});

znData(resourceName).save([params], data, successCallback, errorCallback)

If params is present and contains the id param, performs a PUT. Otherwise performs a POST request.

// Add a workspace member
// equivalent to: POST /workspaces/123/members
znData('WorkspaceMembers').save({ workspaceId:123 }, { 'inviteCode' : 123456 }, function(member) {
    $scope.member = member;
});

// Update a workspace member to be an admin
// equivalent to: PUT /workspaces/123/members/456
znData('WorkspaceMembers').save({ workspaceId:123, id:456 }, { 'role.id' : 2 }, function(members) {
    $scope.members = members;
});

// Make all admins of workspace 123 owners
// equivalent to: PUT /workspaces/123/members?role.id=1
znData('WorkspaceMembers').save({ workspaceId:123, 'role.id': 2 } , { 'role.id' : 1 }, function(members) {
    $scope.members = members;
});

znData(resourceName).update([params], data, successCallback, errorCallback)

Works the same as the save with the execption it will always performs a PUT.

// Update a workspace member to be an admin
// equivalent to: PUT /workspaces/123/members/456
znData('WorkspaceMembers').update({ workspaceId:123, id:456 }, { 'role.id' : 2 }, function(members) {
    $scope.members = members;
});

znData(resourceName).delete(params, successCallback, errorCallback)

Performs a DELETE request. Same as calling del(params, successCallback, errorCallback);

// Delete a workspace member
// equivalent to: DELETE /workspaces/123/members/456
znData('WorkspaceMembers').delete({ workspaceId:123, id:456 }, function() {
    znMessage('Member removed from workspace', 'saved');
});

znData(resourceName).saveAll(params, data, successCallback, errorCallback)

Performs a POST request with multiple objects to be created.

// Create multiple tasks at once
// equivalent to: POST /tasks

$scope.tasks = [
    {
        "task":"Test 1",
        "workspace":{"id":62},
        "taskList":{"id":0},
        "order":1,
        "due":"2015-03-20",
        "assignedToUser":{"id":9},
        "priority":1,
        "status":"open"
    },
    {
        "task":"Test 2",
        "workspace":{"id":62},
        "taskList":{"id":0},
        "order":1,
        "due":"2015-03-20",
        "assignedToUser":{"id":9},
        "priority":1,
        "status":"open"
    },
    {
        "task":"Test 3",
        "workspace":{"id":62},
        "taskList":{"id":0},
        "order":1,
        "due":"2015-03-20",
        "assignedToUser":{"id":9},
        "priority":1,
        "status":"open"
    }
];

znData('Tasks').saveAll({}, $scope.tasks, function(data) {
    znMessage('All tasks saved.', 'saved');
    // `data` will contain IDs of created tasks
});

znData(resourceName).updateAll(params, data, successCallback, errorCallback)

Performs a PUT request. The data param needs to be an object with the properties to be updated for all record that matches the params/conditions.

// Update all tasks status to `closed` where the status is `in-progress`
// equivalent to: PUT /tasks/?status=in-progress

var params = { status: 'in-progress' };
var data = { status: 'closed' };

znData('Tasks').updateAll(params, data, function() {
    znMessage('All tasks updated.', 'saved');
});

// Update all tasks status to `archived` where the IDs are 1, 2, 3
// equivalent to: PUT /tasks/?id=1|2|3

var params = { id: '1|2|3' };
var data = { status: 'archived' };

znData('Tasks').updateAll(params, data, function() {
    znMessage('All tasks archived.', 'saved');
});

znData(resourceName).deleteAll(params, successCallback, errorCallback)

Performs a DELETE request.

// Delete all tasks with status `archived`
// equivalent to: DELETE /tasks/?status=archived

var params = { status: 'archived' };

znData('Tasks').deleteAll(params, function() {
    znMessage('All tasks deleted.', 'saved');
});

// Delete all tasks with IDs 1, 2, 3
// equivalent to: DELETE /tasks/?id=1|2|3

var params = { id: '1|2|3' };

znData('Tasks').deleteAll(params, function() {
    znMessage('All tasks deleted.', 'saved');
});

Param Type Details
params (optional) Object Optional if the resource has no required URL parameters and a POST is desired. Valid URL parameters are defined for each resource here. If the paramsobject is passed, any keys that aren't URL parameters are sent as query parameters in the request. Some examples of valid query parameters are limit, related, sort, and attributes. If the id param is included in this object, a PUT is made. If not, a POST is made.
data Object Sent as the payload of the request.
successCallback function(data, metaData, headers)

The function to execute if the request succeeds.

  • data - {Object} - The data of the response.
  • metaData - {Object} - An object containing the following info about the response:
    • status
    • code
    • totalCount
    • limit
    • offset
    Click here for more info about the response format.
  • headers - {function([headerName])} – Getter function for the HTTP response headers.
errorCallback function(resp)

The function to execute if the request fails. Click here for more info about the format of the failure response.

Available Resources

The parameterized URL is used to query the Zengine REST API. For example, if the resource name is FormFields, the parameterized URL is /forms/:formId/fields/:id. In this case, formId is a required URL paramter, and must be passed to the params argument of any get(), query(), delete(), or save() called on znData('FormFields'). The id parameter on the other hand, may or may not be passed, depending on whether the request is intended for a single object or multiple objects. This is true for the id parameter of any resource URL.

The Zengine REST API has more querying options for pagination, sorting, filtering, and relational data.

Resource Name Parameterized URL
Activities/activities/:activityId
AppTemplates/app_templates/:id
AppTemplateInstallJobs/app_template_install_jobs/:id
BinaryExportBatch/binary_export_jobs/:binaryExportJobId/batches/:id
BinaryExportJob/binary_export_jobs/:id
Calculate/calculate
CalculationSettings/calculation_settings/:id
DataViews/data_views/:id
Events/events/:id
Files/files/:id
Forms/forms/:id
DefaultFormPermissions/forms/permissions
FormFields/forms/:formId/fields/:id
FormFieldTaxonomy/form_field_taxonomy
FormFolders/forms/:formId/folders/:id
FormGroups/forms_groups/:id
FormRecordPermissions/forms/:formId/records/permissions
FormRecords/forms/:formId/records/:id
FormUploads/forms/:id/uploads
Notes/notes/:id
NoteReplies/notes/:noteId/replies/:id
Notifications/notifications/:id
NotificationEmails/notification_emails/:id
Plugins/plugins/:pluginId
PluginScreenshots/plugins/:pluginId/screenshots
PluginServices/plugins/:pluginId/services/:id
PluginServiceUploads/plugins/:pluginId/services/:serviceId/uploads
WorkspacePluginLinks/workspace_plugin_links/:id
RecordImportFiles/record_import_files/:id
RecordImportJobs/record_import_jobs/:id
RecordExportJobs/record_export_jobs/:id
ScheduledWebhooks/scheduled_webhooks/:id
Tasks/tasks/:id
TaskLists/task_lists/:id
TaskPriorities/task_priorities
TaskStatuses/task_statuses
TaskPreferences/users/:userId/task_preferences
Users/users/:id
Roles/workspaces/:workspaceId/roles/:id
WebhookEvents/webhook_events/:id
Webhooks/webhooks/:id
Workspaces/workspaces/:id
WorkspaceCopyJobs/workspace_copy_jobs
WorkspaceInvitees/workspaces/:workspaceId/invitees/:id
WorkspaceMembers/workspaces/:workspaceId/members/:id
WorkspaceTransferRequests/workspaces/:workspaceId/transfer_requests/:id
WorkspaceTaskPreferences/workspaces/:workspaceId/members/:memberId/task_preferences
WorkspaceLogo/workspaces/:workspaceId/logo
Countries/countries
States/states
Subscriptions/subscriptions/:id

znPluginData

The znPluginData service is used to communicate with Plugin Services, similar to how znData makes requests to the REST API. Instead of passing a resource name, you pass the plugin namespace and service route. The methods available are: get, post, put, and delete. The methods return an Angular promise object.

The param workspaceId is always required and must be a workspace where the plugin is installed. Query string parameters should be passed as params.


znPluginData(namespace).get(route, params, successCallback, errorCallback)

Performs a GET request.

// equivalent to: GET https://plugins.zenginehq.com/workspaces/123/myPlugin/my-route?id=456
znPluginData('myPlugin').get('/my-route', { workspaceId: 123, params: { id: 456 }}, function(results) {
    $scope.results = results;
});

znPluginData(namepsace).post(route, params, data, successCallback, errorCallback)

Performs a POST request.

// equivalent to: POST https://plugins.zenginehq.com/workspaces/123/myPlugin/my-route
znPluginData('myPlugin').post('/my-route', { workspaceId: 123 }, { name: $scope.name }, function(result) {
    $scope.result = result;
});

znPluginData(namespace).put(route, params, data, successCallback, errorCallback)

Performs a PUT request.

// equivalent to: PUT https://plugins.zenginehq.com/workspaces/123/myPlugin/my-route?id=456
znPluginData('myPlugin').put('/my-route', { workspaceId: 123, params: { id: 456 }}, { email: $scope.email }, function(result) {
    $scope.result = result;
});

znPluginData(namespace).delete(route, params, successCallback, errorCallback)

Performs a DELETE request.

// equivalent to: DELETE https://plugins.zenginehq.com/workspaces/123/myPlugin/my-route?id=456
znPluginData('myPlugin').delete('/my-route', { workspaceId: 123, params: { id: 456 }}, function(result) {
    // Deleted
});

znPluginEvents

znPluginEvents is service that acts as a wrapper for the Angular pub-sub system, and is meant for communication between plugins and the core app.

znPluginEvents.$on(name, listener)

Same as Angular $on. This method can be used to listen for the following broadcasted events:

  • zn-ui-record-overlay-record-loaded
  • zn-data-resource-name-action
    • Events in this format are triggered by a successful response to a call via the znData service. The resource name is the hyphenated version of the resource names listed here. The action can be one of the following: read, saved, deleted, saved-all, updated-all or deleted-all. For example, calling znData('FormRecords').save() will trigger the 'zn-data-form-records-saved' event.

Important: Make sure to deregister your listeners when your plugin is destroyed. Not deregistering listeners will cause listeners to duplicate and pile up, which will degrade the performance of your plugin and the app. The code below shows listeners being registered and deregistered on $scope $destroy.

/**
 * Plugin testPluginEvents Controller
 */
plugin.controller('testPluginEventsCntl', ['$scope', 'znPluginEvents', function ($scope, znPluginEvents) {

    // zn-ui-record-overlay-record-loaded
    var recordLoaded = znPluginEvents.$on('zn-ui-record-overlay-record-loaded', function(evt, record) {
        console.log(record);
    });

    // zn-data-[resource name]-saved
    var recordSaved = znPluginEvents.$on('zn-data-form-records-saved', function(evt, record, created, params) {
        if (created) {
            console.log('Record ' + record.id + ' was created in form ' + params.formId);
        } else {
            console.log('Record ' + record.id + ' was updated in form ' + params.formId);
        }
    });

    // zn-data-[resource name]-deleted
    var recordDeleted = znPluginEvents.$on('zn-data-form-records-deleted', function(evt, params) {
        console.log('Record ' + params.id + ' was deleted');
    });

    // zn-data-[resource name]-read
    var recordRead = znPluginEvents.$on('zn-data-form-records-read', function(evt, records, params) {
        angular.forEach(records, function(record) {
            console.log(record);
        });
    });

    // zn-data-[resource name]-saved-all
    var taskSaveAll = znPluginEvents.$on('zn-data-tasks-saved-all', function(evt, data, params) {
        console.log('Tasks IDs created: ' + data.join(','));
        // `data` will be an array of IDs
    });

    // zn-data-[resource name]-updated-all
    var taskUpdateAll = znPluginEvents.$on('zn-data-tasks-updated-all', function(evt, params) {
        console.log('Tasks was updated');
        // `params` will contain the path and query params used
    });

    // zn-data-[resource name]-deleted-all
    var taskDeleteAll = znPluginEvents.$on('zn-data-tasks-deleted-all', function(evt, params) {
        console.log('Tasks was deleted');
        // `params` will contain the path and query params used
    });

    // Deregister listeners
    $scope.$on("$destroy", function() {
        if (recordLoaded) recordLoaded();
        if (recordSaved) recordSaved();
        if (recordDeleted) recordDeleted();
        if (recordRead) recordRead();
        if (taskSaveAll) taskSaveAll();
        if (taskUpdateAll) taskUpdateAll();
        if (taskDeleteAll) taskDeleteAll();
    });

}]);

znLocalStorage

This service gives you basic access to browser local storage and fallbacks to browser cookies if support is not available.

znLocalStorage.set(key, value)

Set an item in browser local storage.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testLocalStorageCntl', ['$scope', 'znLocalStorage', function ($scope, znLocalStorage) {

  znLocalStorage.set('lastSaved', new Date());

}]);

znLocalStorage.get(key)

Get an item in browser local storage.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testLocalStorageCntl', ['$scope', 'znLocalStorage', function ($scope, znLocalStorage) {

  znLocalStorage.get('lastSaved');

}]);

znLocalStorage.remove(key)

Remove an item in browser local storage.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testLocalStorageCntl', ['$scope', 'znLocalStorage', function ($scope, znLocalStorage) {

  znLocalStorage.remove('lastSaved');

}]);

znLocalStorage.isSupported

Checks if the browser support local storage.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testLocalStorageCntl', ['$scope', 'znLocalStorage', function ($scope, znLocalStorage) {

  if (znLocalStorage.isSupported) {
    // is supported
  } else {
    // not supported
  }

}]);

znCookies

This service gives you basic access to browser cookies.

znCookies.set(key, value)

Set an item in browser cookies.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testCookiesCntl', ['$scope', 'znCookies', function ($scope, znCookies) {

  znCookies.set('lastSaved', new Date());

}]);

znCookies.get(key)

Get an item in browser cookies.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testCookiesCntl', ['$scope', 'znCookies', function ($scope, znCookies) {

  znCookies.get('lastSaved');

}]);

znCookies.remove(key)

Remove an item in browser cookies.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testCookiesCntl', ['$scope', 'znCookies', function ($scope, znCookies) {

  znCookies.remove('lastSaved');

}]);

znCookies.isSupported

Checks if the browser support cookies.

/**
 * Plugin testLocalStorage Controller
 */
plugin.controller('testCookiesCntl', ['$scope', 'znCookies', function ($scope, znCookies) {

  if (znCookies.isSupported) {
    // is supported
  } else {
    // not supported
  }

}]);