Version 3

    Cartridges SDK 3.0 gives you full access to the new AngularJS framework used by Jive Anywhere 3.0, including all existing directives (UI components), services, icons and CSS-files. If you are not yet familiar with AngularJS, please take the time to read the tutorials on


    To create a new AngularJS-aware IFRAME, use PageModuleContext.createFrame() in pagescript.js

    PageModuleContext.createFrame(frameId, params, templateUrl, scriptUrls);

    For instance:

    var frame = PageModuleContext.createFrame('framePeopleSearch', { serverUrl: null }, 'frame.html', ['frame.js', 'directives.js']);


    The height of the frame is managed automatically to fit its content. Filenames are relative to the root folder of the cartridge that is packed in a zip file.


    The templateUrl file should use a controller defined in the script file. It should also have a jive:connection directive used to maintain a connection to a Jive instance for all child elements.

    <div ng-controller="testController" jive:connection="onConnectionReady(dp)">
        <style jive:cartridge-css-src="style.css"></style>
        <img jive:cartridge-src="icon.png" />
        <span class="icon"></span>
        <test:user-search message="Please enter a username"></test:user-search>


    Use jive:cartridge-src attribute to reference local cartridge image files.

    <img jive:cartridge-src="icon.png" />

    Use jive:cartridge-css-src to import CSS files.

    <style jive:cartridge-css-src="style.css"></style>

    Inside the CSS you can use the "!/" prefix to reference local image files.

    .icon {
      background: url('!/icon.png');
      width: 16px;
      height: 16px;
      display: block;


    In frame's script files the following members are provided: angular, $, params and module. Use module to declare new AngularJS controllers and directives in your cartridge's module.

    module.controller('testController', function ($scope, JCommon, BgProvider, CartridgeProvider) {
      // wait for default connection to be initialized
      $scope.onConnectionReady = function (dp) {
          // dp is an instance of DataProvider for the default account


    Both ModuleContext and PageModuleContext are not available from within frame's script files, instead you should be using the BgProvider and CartridgeProvider services and an instance of DataProvider service to pass messages and requests between the frame context and the background or page contexts.


    Use CartridgeProvider.sendMessageToModule() to send messages and receive responses from module.js. You can then execute custom requests and access ModuleContext and ClientFacade in the background context.

    CartridgeProvider.sendMessageToModule(command, data, callback);

    Use CartridgeProvider.sendMessageToFrame() to send messages and receive responses from another frame. The frameId used in createFrame should be passed to this method. This method can also be executed using the ModuleContext and PageModuleContext objects.

    CartridgeProvider.sendMessageToFrame(frameId, command, data, callback);

    Use CartridgeProvider.runPageScript() to call methods on pagescript.js and receive responses.

    CartridgeProvider.runPageScript(funcName, params, callback);

    Use CartridgeProvider.moduleCommand.on(callback) to receive events for incoming messages sent by other frames, page and module contexts. A message has command, data and sendResponse properties.

    CartridgeProvider.moduleCommand.on(function (message) {
      if (message.command == "test") {


    Use CartridgeProvider.getContent() to get content of a local file.

    CartridgeProvider.getContent(url, callback);

    Use dp (instance of DataProvider) to execute predefined server requests to Jive. It is a wrapper to ClientFacade that lives in the context of module.js by sending messages to the background context.

    dp.searchUsers("a", 10, callback);

    If you want to use a non-default account, you can change the current instance of dp using dp.set(connection). You can get a connection object by calling BgProvider.getConnection or BgProvider.getConnections. A null server URL parameter will return a connection for the default account. Changing dp will affect all components inside the element with jive:connection directive as this instance of DataProvider is bound to this element.

    BgProvider.getConnection(params.serverUrl, function (connection) {
      // we must initialize the connection by requesting its settings first
      dp.getSettings(function (settings) {
          // keep the settings on the scope for later use
          $scope.settings = settings;


    In directives, use the "!/" prefix to reference local template files.

    • In ng-include directive: <ng-include src="'!/template.html'">
    • In custom directives: templateUrl: '!/template.html'



    Creating the test:user-search directive (Sample)

    Directives in AngularJS are UI components with logic, events and properties. Here is a simple demonstration of a search-users directive. It contains a label, textbox and list of users that were found.

    module.directive('testUserSearch', function () {
      return {
          restrict: 'E',
          transclude: false,
          require: '^jiveConnection',
          scope: {
            message: '@'
          templateUrl: '!/templates/searchTemplate.html',
          link: function (scope, element, attrs, connCtrl) {
          controller: function ($scope) {
            $scope.onConnectionReady = function (dp) {
                $ = function () {
                  dp.searchUsers($scope.username, 10, function (response) {
                      $scope.users = response.people;


    And here is the content of searchTemplate.html:

        {{message}}<br />
        <input type="text" ng-model="username" />
        <button ng-click="search()">search</button>
        <div ng-repeat="user in users">
            <jive:user-avatar user="user" css-class="small" style="display: inline-block; vertical-align: middle;"></jive:user-avatar>
            <jive:user-link user="user" style="vertical-align: middle;"></jive:user-link>


    The following HTML will then produce this view:

    <test:user-search message="Please enter a username"></test:user-search>


    Built-in Directives

    Most of the UI components in Jive Anywhere were created as directives and thus are completely reusable and exposed to the Cartridges SDK. Some of the directives use the attached connection (jive:connection attribute on parent's element) to execute server requests (for instance the jive:like directive), while some others just fire events and let you manually perform the required server logic. Directives can also contain other directives in order to create a complex directive such as jive:jview, jive:activity and jive:content. The diagrams below gives you an instance of how these directives are used in Jive Anywhere.



    • <img jive:cartridge-src="icon.png">
    • <style jive:cartridge-css-src="style.css"></style>

    Item Actions

    • <jive:like item="item" on-click="onClick(item, liked)">
    • <jive:likes-popup users="users" loading="false" visible="false">
    • <jive:user-rating item="item" on-click="onClick(item, rating)">
    • <jive:average-rating item="item">
    • <jive:item-actions item="item">
    • <jive:comment-actions comment="comment" discussion-item="item">
    • <jive:outcome-badges item="item" discussion-item="item">
    • <jive:actions-popup on-item-marked-outcome="onItemMarkedOutcome(item)" on-item-marked-correct="onItemMarkedCorrect(item, isCorrect)">

    People and Places

    • <jive:user-link user="user">
    • <jive:user-info-popup user="user" loading="false" visible="true">
    • <jive:user-avatar user="user" no-link="false" css-class="big">
    • <jive:user-profile-img user="user" size="200" css-class="">
    • <jive:user-picker on-query="onQuery(text, callback)" items="items" allow-add-items="true" placeholder="Search people" limit="10" on-items-changed="onChanged(item, items, changed)">

    Popups and Modals

    • <jive:popup name="testPopup" visible="true" move-to-nearest-container-css-class="" top="0" left="0" below-offset="0" relative-element="element" relative-use-center="true" relative-to-previous-element="false">This is content in popup</jive:popup>
    • <a jive:popup-trigger="testPopup" on-open="onOpen(popupScope)" show-on-hover="false">Click to open</a>
    • <jive:modal visible="false" close-on-click="true" on-close="onClose()" move-to-nearest-container-css-class="">This is content in modal</jive:modal>

    User Content

    • <jive:content-body html="html">
    • <jive:reply-form on-submit="onSubmit(html)" on-cancel="onCancel()" submit-text="Post" loading="false" error-message="">
    • <jive:at-mentions-input html-getter="htmlGetter" auto-focus="true" is-empty="isEmpty">

    Complex Components

    • <jive:jview item-id="id" item-type="typeId" anchor-comment-id="commentId" hide-main-discussion="false" on-load="onLoad(item)" on-scroll-top="onScrollTop(top)" embedded="true" max-indent="4">
    • <jive:content container-type="typeId" container-id="id" filter="0" sort="0" limit="10" page="1" open-item-external="false" on-open-item="onOpenItem(itemId, itemType)">
    • <jive:activity container-type="typeId" container-id="id" limit="10" open-item-external="false" on-open-item="onOpenItem(itemId, itemType)">
    • <jive:people container-type="typeId" container-id="id" limit="10" page="1">

    Misc. Components

    • <div jive:connection="onConnectionReady(dp)"></div>
    • <jive:connections-popup connection="connection" on-select="onSelect(connection)" disabled="false">
    • <div jive:prevent-scroll="true" style="overflow: auto; height: 100px;"></div>
    • <jive:community-icon connection="connection">
    • <jive:object-icon type-id="typeId" icon-css="objectCss" icon-size="med">
    • <jive:pagination page="1" num-pages="5" max-buttons="5" on-click="onClick(page)">
    • <jive:filter-buttons on-click="onClick(filter)" filters="[{name: 'filter1', value: 1}, {name: 'filter2', value: 2}]" allow-ascending="true" selected-filter="filter">
    • <a jive:href="{{user.profile_url}}">View profile</a>


    More info about AngularJS-aware frames is in the attached PDF.

    You can download the Starter Pack from