Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Welcome to Portal SDK. This document is intended to familiarize you with HTML, JavaScript and Server Script components of the SDK.

Other Documents

All HTML should be inside template script tags:

Code Block
languagexml
linenumberstrue
<script type="text/ng-template" id="main.html"> … </script>

The templates are then placed into one of the three columns using Javascript's $scope.portalHelpers.showView function (see the Javascript section for more details).

To ensure that your widget fits well into Portal, it is strongly recommended (but not required) that you use predefined components for common tasks. Feel free to adjust the components to your needs using the CSS tab of the SDK.

Create Row Items (Web Only)

Row item is a generic component most commonly used in lists. It contains styles that ensure elements are properly spaced out and padded and allows the construction of complex items that require multiple columns with vertically centered content.

DirectivesDescription
<widget-row> or <wr>Declares a row component in the widget.
<widget-cell> or <wc>Declares a cell in the row component.
<widget-icon> or <wi>Adds an icon to a widget item.
AttributesDescription
fillForces a cell to expand to a maximum possible width, making any adjacent cells to become minimally small.
clickableMakes a row or a cell clickable.

<widget-row> and <widget-cell> Directives

Basic Syntax

Code Block
languagexml
linenumberstrue
<widget-row>
    <widget-cell>
        I am content.
    </widget-cell>
</widget-row>


Result:

  I am content.

The component starts by declaring a "widget-row" component that must contain one or more "widget-cell" components. While not shown, the element contains appropriate padding and margins.

Multiple Columns

Code Block
languagexml
linenumberstrue
<widget-row>
    <widget-cell>
         Cell_1
    </widget-cell>
    <widget-cell>
         Cell_2
    </widget-cell>
    <widget-cell>
         Cell_3
    </widget-cell>
</widget-row>

Result:

  Cell_1              Cell_2              Cell_3

When there are more than one "widget-cell" components in a "widget-row", they stack horizontally.

<widget-icon> Directive

Basic Syntax

Code Block
languagexml
linenumberstrue
<widget-row>
    <widget-cell fill>
        Bacon ipsum dolor amet porchetta strip steak pastrami picanha.
    </widget-cell>
    <widget-cell>
        <widget-icon name="angle-right"></widget-icon>
    </widget-cell>
</widget-row>

Result:

To add an icon to a widget item, use "widget-icon" directive and "name" attribute to specify which icon should be displayed.

fill Attribute

Adding "fill" attribute to a "widget-cell" component forces that cell to expand to a maximum possible width, making any adjacent cells to become minimally small.

Basic Syntax

Code Block
languagexml
linenumberstrue
<widget-row>
    <widget-cell>
         Cell_1
    </widget-cell>
    <widget-cell fill>
         Cell_2
    </widget-cell>
    <widget-cell>
         Cell_3
    </widget-cell>
</widget-row>

Result:

  Cell_1  Cell_2                                                                                 Cell_3

clickable Attribute

To make the row or a cell clickable, add "clickable" attribute to the "widget-row" or "widget-cell" directive. This will change the background of the clickable element as well as the cursor when user hovers over the element.

Example:

Code Block
languagexml
linenumberstrue
<widget-row clickable>
    <widget-cell fill>
        Bacon ipsum dolor amet porchetta strip steak
        pastrami picanha.
    </widget-cell>
    <widget-cell>
        <widget-icon name="angle-right"></widget-icon>
    </widget-cell>
</widget-row>

Result:

Example: Nesting

"widget-cell" elements may be nested within each other for more flexibility. In this example, only the right side of the widget item is hoverable. To achieve this, the "clickable" attribute is assigned to the second widget-cell that is set to fill maximum possible space. Inside of this widget cell, we create two more widget cells: first one contains the content and is set to fill maximum space using the "fill" attribute; second widget cell contains the angle icon.

Example:

Code Block
languagexml
linenumberstrue
<widget-row>
    <widget-cell>
        <widget-icon name = "star"></widget-icon>
    </widget-cell>
    <widget-cell fill clickable><widget-cell fill>
            Bacon ipsum dolor amet porchetta strip steak pastrami picanha.
        </widget-cell>
        <widget-cell>
            <widget-icon name = "angle-right"></widget-icon>
        </widget-cell>
    </widget-cell>
</widget-row>

Result:

Create Lists (Web and App)

If you have a list of items that you would like to display, use "widget-list" directive. "widget-list" directive offers several benefits over standard angular "ng-repeat" directive (it is essentially a wrapper around ng-repeat with extra features): ability to add pagination controls, highlighting selected items if they link to another widget-view and going through the list items using external controls (such as "next"/"previous" controls on a details page using "widget-list-details-controls" directive). | Directives | Description | | -------- | -------- | |<widget-list>|Declares a list component in the widget.| |<widget-list-controls>|Controls a list externally.| |<widget-add-to-calendar>|Display a button that can add or remove an event to the user calendar.|

AttributesDescription
show-itemsIndicates that the list directive should break down your list into pages. The value of "show-items" attribute represents the number of items to show per page.

<widget-list> Directive

Declares a list component in the widget.

Example: Basic List

JavaScript

Code Block
languagejs
linenumberstrue
$scope.model = [
	{
    title : "item 1",
    details : "item 1 details"
	}, {
    title : "item 2",
    details : "item 2 details"
	}, {
    title : "item 3",
    details  : "item 3 details"
	}, {
    title : "item 4",
    details : "item 4 details"
	}, {
    title : "item 5",
    details : "item 5 details"
	}, {
    title : "item 6",
    details : "item 6 details"
	}];

$scope.ready = true;

HTML (web)

Code Block
languagexml
linenumberstrue
<widget-list list = "item in model">
    <widget-row>
        <widget-cell></widget-cell>
    </widget-row>
</widget-list>

HTML (app)

Code Block
languagexml
linenumberstrue
<widget-list list="item in model track by item.title" render="ready">
    <div class="item item-icon-right item-text-wrap">
        <b ng-bind-html="::item.title"></b>
        <p>
            <b>Details:</b> {{::item.details}}<br />
        </p>
        <i class="icon ion-chevron-right"></i>
    </div>
</widget-list>

Result (web)

Result (app)

To pass your model into the "widget-list" directive, use the "list" attribute. The syntax for the argument is the same as for angular’s "ng-repeat" directive.

<widget-list-controls> Directive

Controls a list externally.

Example: List with External Controls

HTML

Code Block
languagexml
linenumberstrue
<script type="text/ng-template" id="details.html">
    <widget-list-controls prev-click="prevItem" next-click="nextItem" original-item="item" prev-text="Previous Item" next-text="Next Item"></widget-list-controls> 
    ...
</script>

JavaScript

Code Block
languagexml
linenumberstrue
$scope.prevItem = function () {
    var prevItem = $scope.portalHelpers.getPrevListItem();
    $scope.showDetails(prevItem);
}
$scope.nextItem = function () {
    var nextItem = $scope.portalHelpers.getNextListItem();
    $scope.showDetails(nextItem);
}

Result

In order to be able to control the list externally, you can use the "widget-list-controls" directive. The "prev-click" and "next-click" attributes indicate what functions to run when user presses previous and next buttons. "original-item" attribute must map to the scope variable that represents the currently selected item. "prev-text" and "next-text" indicate what text to use for the navigation buttons. Within your "prev-click" and "next-click" call $scope.portalHelpers.getPrevListItem() or $scope.portalHelpers.getNextListItem() to retrieve previous and next items from a list that user has interacted with last. When these functions are called, Portal programmatically selects a new item in the list and then returns that item.

Preventing Page Resetting

By default the directive will watch for changes in the itemList and refresh the list. When the list gets refreshed, the pagination controls get reset. If this is not a desired behaviour, use $scope.$broadcast(‘ignoreListChanges’); to ignore changes to the list during current digest cycle.

This is useful when you update a field in one of the items without altering the number of items that appear in the list. An example of this is the "Crowd Reporter" widget: when user submits a report, the value of the bar changes. Without calling $scope.$broadcast(‘ignoreListChanges’); user would be taken to the first page of the widget after each report.

Optionally, you can pass second argument, id, which specifies on which list to ignore changes, specifically. The id must match the attribute specified on the "widget-list" directive:

Code Block
languagexml
linenumberstrue
<widget-list list="setting in newsSettings.value" show-items="8" id="newsPaginate1">

and then

Code Block
languagejs
linenumberstrue
  $scope.$broadcast('ignoreListChanges', 'newsPaginate1');

This is useful when a page contains more than one list and interactions with one make changes to another list.

<widget-add-to-calendar> Directive

Use this directive to create a button that can add or remove an event from the user calendar. You need to specify the following attributes for this directive:

Code Block
languagexml
linenumberstrue
<widget-add-to-calendar identifier="Id" location="Location" summary="Summary" description="Description" start="StartDate" end="EndDate"></widget-add-to-calendar>
  • identifier: a unique identifier of the calendar entry.
  • location: the location of the calendar entry.
  • summary: the title of the calendar entry.
  • description: the description of the calendar entry.
  • description: the description of the calendar entry.
  • end: the ending time of the calendar entry.

show-items Attribute

Indicates that the list directive should break down your list into pages. The value of "show-items" attribute represents the number of items to show per page.

Basic Syntax

Code Block
languagexml
linenumberstrue
<widget-list list="item in model" show-items="3">
    <widget-row>
        <widget-cell></widget-cell>
    </widget-row>
</widget-list>

Result

Example: List with Pagination

HTML

Code Block
languagexml
linenumberstrue
<widget-list list="item in model" show-items="3">
    <widget-row clickable ng-click="showDetails(item)">
        <widget-cell fill></widget-cell>
        <widget-cell>
            <widget-icon name="angle-right"></widget-icon>
        </widget-cell>
    </widget-row>
</widget-list>

Details view

Code Block
languagexml
linenumberstrue
<script type="text/ng-template" id="details.html">
    <widget-row>
        <widget-cell>
            <h3></h3>
        </widget-cell>     
    </widget-row>     
    <widget-row>
        <widget-cell>
            <div class="pHighlight"></div>
        </widget-cell>
    </widget-row> 
</script>

Javascript

Code Block
languagexml
linenumberstrue
$scope.showDetails = function (item) {
    $scope.item = item;
    $scope.portalHelpers.showView('details.html', 2);
};

Result

Now when the user clicks the item, they invoke the "showDetails" function in the controller. This function takes the "item" argument which corresponds to the list item object that the user has selected. Clicking an item in the "widget-list" directive that has a "clickable" attribute, marks that element as selected, resulting in markup changes that get decorated with CSS (in this case the element with "clickable" attribute has it’s background changed to indicate that it is selected). This is done by setting the list with which the user has interacted as "active" (in case there is more than one list in a view) and by setting "$$selected" property of the item to true (you can see this by typing $scope.item.$$selected in the console while inspecting the list item).

Create Search Controls

Once you have applied pagination controls to deal with long lists, it may also be useful to let the user search through the list using textual input or to filter the list by a set of categories. To perform these tasks, you can use the following directives.

DirectivesDescription
<widget-search>Declares a search component in the widget.
<widget-filter>Adds filter options to a search component.

<widget-search> Directive

Declares a search component in the widget.

Code Block
languagexml
linenumberstrue
<widget-search label="What do you seek, padawan?" 
    placeholder= "Type in a search term you must" 
    search-results-title="Behold" 
    data="model"
    min-char="2" fields="['title','details']">
    <widget-searching>
        <widget-list list="item in searchResults" show-items="3">
            <!-- List template goes here... -->
        </widget-list>
    </widget-searching>
    <widget-not-searching>
        <!-- Components to display when user is not searching... -->
    </widget-not-searching>
</widget-search>

Result

"widget-search" directive takes following arguments:

  • label: text to put above the input box
  • placeholder: text to show inside the input box when it’s empty
  • search-results-title: how to title search results
  • data: the list of items to search through
  • min-char: minimum number of characters required to initiate search
  • fields: an array of field names to check when searching through the list of items

Within the "widget-search" directives two other directives are nested: "widget-searching" directive and the "widget-not-searching" directive. The "widget-searching" directive becomes visible when user is performing searching, while "widget-no-searching" is visible when user is not searching, respectively. This is useful if you have complex content that needs to be displayed when user is not searching, or if the template of the searched list differs from the one that is shown initially.

In this example we are using the list of items that was declared in the previous example and bound to a scope variable "model". When user types in a search term, the directive checks the "title" and "details" properties of each item in the "model" list and makes the filtered list available as the searchResults array variable. We iterate over that list when user is searching by placing a "widget-list" directive inside the "widget-searching" directive.

<widget-filter> Directive

Adds filter options to a search component.

Example: Search Control with Filter options

Code Block
languagexml
linenumberstrue
<widget-search ...>
    <widget-filter  fields="['category']"
        filters="[{value:'1',text:'Number 1'},{value:'2',text:'Number 2'}]"
        title ="Pick a category">
    </widget-filter>
    …
</widget-search>

Result

We modified our data to include an additional field: "category". Items 1,3 and 5 have their "category" property set to "1" and 2,4 and 6 to "2". To let user filter the list by one or other category, we include a "widget-filter" directive. It takes the following arguments:

  • title: label text for the button group
  • fields: which object properties to check for filter text
  • filters: the list of filters for the user to pick from. "value" corresponds to the search term that is going to be checked against the properties specified in the "fields" attribute and "text" is the text that is going to be shown to the user.