Building A Custom Widget: Angular Stock Ticker Widget - akumina/AkuminaTraining GitHub Wiki

Custom Widget - Angular Stock Ticker

In this example, we will build the stock ticker widget (from https://github.com/akumina/AkuminaTraining/wiki/Building-A-Custom-Widget:-Stock-Ticker-Widget) using AngularJS (https://angularjs.org/).

This example assumes that angular is included on the site, as part of the master page

For this example our app is "stockTickerApp" and our controller is "stockTickerCtrl".

Screenshot

image 10

How to Deploy

  1. Download digitalworkplace.custom.js from the “/Style Library/DigitalWorkplace/JS” folder within SharePoint
  2. Paste the Widget Definition within digitalworkplace.custom.js
  3. Upload the updated digitalworkplace.custom.js to the “/Style Library/DigitalWorkplace/JS” folder within SharePoint
  4. In the Management Apps tab of AppManager, click on the View Manager. Click “Add New”. In the left pane navigate to “/DigitalWorkplace/Content/Templates/” for the folder path. Click “Choose File”, navigate to your custom template (StockList.html). Click “Save”. Repeat for StockListChart.html.
  5. In the Management Apps tab of AppManager, click on the Widget Manager app. Then click on Add Widget. Create your widget with the values in the Widget Manager – Widget Definition section. Click Save & Exit
  6. In the Manage Widgets window, find StockTicker and click its ‘View Widget Definitions’ button. Then click on ‘Add New’. Create your widget instance with the values in the Widget Manager – Widget Instance section. Click Save & Exit
  7. Copy the Widget Snippet of your Widget Instance.
  8. Paste the snippet into a Content Editor Web Part on a page within the site. Publish the page.
  9. Flush your cache by clicking on the Akumina icon in the left rail, clicking the refresh icon, then clicking “Refresh All Cache”
  10. Refresh the page. You will see your Stock Ticker Widget

Widget Definition

if ((typeof Akumina.AddIn.StockTickerWidget) === 'undefined') {
	Akumina.AddIn.StockTickerWidget = function () {
		var _cur = this;
		
		this.GetPropertyValue = function (requestIn, key, defaultValue) {
            var propertyValue = "";

            for (var prop in requestIn) {
                if (key.toLowerCase() == prop.toLowerCase()) {
                    propertyValue = requestIn[prop];
                    break;
                }
            }

            return (propertyValue == undefined || propertyValue.toString().trim() == "") ? defaultValue : propertyValue;
        };
		
		this.SetDefaultsProperties = function (requestIn) {
            var requestOut = requestIn;

            requestOut.SenderId = _cur.GetPropertyValue(requestIn, "id", "");
            requestOut.DisplayTemplateUrl = _cur.GetPropertyValue(requestIn, "displaytemplateurl", "");
            requestOut.StockList = _cur.GetPropertyValue(requestIn, "stocklist", "");
            requestOut.callbackMethod = _cur.GetPropertyValue(requestIn, "callbackmethod", "");

            return requestOut;
        };
		
		this.Init = function (StockTickerRequest) {
            _cur.appWebUrl = decodeURIComponent(Akumina.AddIn.Utilities.getQueryStringParameter("SPAppWebUrl", ""));
            _cur.hostUrl = decodeURIComponent(Akumina.AddIn.Utilities.getQueryStringParameter("SPHostUrl", ""));
            _cur.StockTickerRequest = _cur.SetDefaultsProperties(StockTickerRequest);
            _cur.StockTickerRequest.EditMode = Akumina.AddIn.Utilities.getEditMode();
			var widgetName = "StockTicker";
            Akumina.Digispace.WidgetPropertyViews.AddViewForProperty(widgetName, "DisplayTemplateUrl", "TemplatePicker");
			
            _cur.Prerender();
        };
		
		this.Prerender = function () {
            var targetDiv = this.StockTickerRequest.SenderId;
            $("#" + targetDiv).html(Akumina.Digispace.ConfigurationContext.LoadingTemplateHtml);
            Akumina.Digispace.AppPart.Eventing.Subscribe('/loader/completed/', _cur.Render);
			Akumina.Digispace.AppPart.Eventing.Subscribe('/widget/updated/', _cur.RefreshWidget);
        };
		
		this.Render = function () {
            
            var stocklist = _cur.StockTickerRequest.StockList;
			
			$.getJSON('https://finance.google.com/finance/info?client=ig&q=' + stocklist + '&callback=?', function (response) {
						_cur.Success(response);
			});
		};
		
		this.RefreshWidget = function (newProps) {
		
			if (newProps["id"] == _cur.StockTickerRequest.SenderId) {
				_cur.StockTickerRequest = _cur.SetDefaultsProperties(newProps);
				_cur.Render();
			}
		
		};
		
		this.Success = function(response)
		{
			var data = {};
		    data.Items = [];
			data.SenderId = _cur.StockTickerRequest.SenderId;
			for (i = 0; i < response.length; i++) {
				var stockInfo = response[i];	
				var title = stockInfo.t;
				var url = "http://finance.yahoo.com/q?s=" + stockInfo.t;
				var chart = "https://www.google.com/finance/getchart?q=" + stockInfo.t + "&p=5d&i=240";
				var changeValue = parseFloat(stockInfo.c);
				var changeIsPositive = changeValue >= 0;
				var stockPrice = stockInfo.l;
				var differential = stockInfo.c;
				var percent = stockInfo.cp;
				var time = stockInfo.lt;
					
					
				var stockItem = {
					"Title": title,
					"StockTitle": title, 
					"Url": url,
					"Positive": changeIsPositive,
					"Price": stockPrice,
					"Differential": differential,
					"Percent": percent,
					"Time": time,
					"Chart": chart

				};                    
				data.Items.push(stockItem);
		    }				
			
		    if (!_cur.StockTickerRequest.EditMode) {
				_cur.BindTemplate(_cur.StockTickerRequest.DisplayTemplateUrl, data, _cur.StockTickerRequest.SenderId);
		    }		
		};
            
		this.BindTemplate = function (templateUri, data, targetDiv) {
			new Akumina.Digispace.AppPart.Data().Templates.ParseTemplate(templateUri, data).done(function (html) {
			    $("#" + targetDiv).html(html);

			    // we call our angular code here
			    var app = angular.module("stockTickerApp", []);
			    app.controller("stockTickerCtrl", function($scope) {
			    	$scope.Items = data.Items
			    });
			    // init the stockTickerApp
			    angular.bootstrap(document, ['stockTickerApp']);
		    });
		};
	}
};

if ((typeof Akumina.AddIn.StockTickerWidget) === ‘undefined’)

We define the Stock Ticker widget with this line.

this.GetPropertyValue

Helper method to get properties

this.SetDefaultProperties

We set the default values to properties if nothing is passed in for them.

this.Init

this.Init calls the functions to render the widget. We also specify the widget name that we will use for the Widget Class step and we subscribe the widget to the Template Picker.

this.Prerender

this.Prerender defines what will show while the widget is rendering. We use subscriptions to call the this.Render function when loading is complete and this.RefreshWidget when the widget is updated.

this.Render

We make a GET call to google finance with our stocklist values as paramters. Upon successful query we call the Success function

this.Success

We assign the results from our GET to values to be used in our template

this.BindTemplate

We bind our data to our template and render. We also call our Angular bootstrap here.

this.RefreshWidget

this.RefreshWidget resets the properties and calls this.Render

Template

IMPORTANT: In our templates, we escape our tokens (Example: {{token}}) so that they are not processed by handlebars.

Create a file called StockTicker.html and paste the following markup within

<style>
    .ia-announcement-wrapper
    {
        background-color:white; 
		padding:10px;
    }
</style>
<div class="interAction" ng-app="stockTickerApp" ng-controller="stockTickerCtrl">
    <div class="ia-announcement-wrapper">
        <div class="ia-announcements">
            <ul>
                <li ng-repeat="Item in Items">
                    <h4 class="ia-announcement-title"><a href="\{{Item.Url}}">\{{Item.StockTitle}}</a></h4>
                    <p class="ia-annoucement-summary">\{{Item.Price}} 
                    <font color="green" ng-if="Item.Positive == true"> \{{Item.Differential}} (\{{Item.Percent}}%)</font>
                    <font color="red" ng-if="Item.Positive == false"> \{{Item.Differential}} (\{{Item.Percent}}%)</font>
                    <br/>
                    \{{Item.Time}}</p>
                </li>
            </ul>
        </div>
    </div>
</div>

Create a file called StockTickerChart.html and paste the following markup within

<style>
    .ia-announcement-wrapper
    {
        background-color:white; 
		padding:10px;
    }
</style>
<div class="interAction" ng-app="stockTickerApp" ng-controller="stockTickerCtrl">
    <div class="ia-announcement-wrapper">
        <div class="ia-announcements">
            <img class="stockticker-chart" src="\{{Item.Chart}}" title="\{{Item.StockTitle}}" alt="\{{Item.StockTitle}}" ng-repeat="Item in Items">
        </div>
    </div>
</div>

Widget Manager - Widget Definition

image 11

WidgetName

StockTicker

WidgetClass

Akumina.AddIn.StockTickerWidget

WidgetProperties

Property Name

Stocklist

Property Value

MSFT,APPL,ATVI,AMZN,GOOG

Property Type

Text

###WidgetViews image 12

View 1

View Name

View 1

Relative Template Url

/Style Library/DigitalWorkplace/Content/Templates/StockList.html

View 2

View Name

View 2

Relative Template Url

/Style Library/DigitalWorkplace/Content/Templates/StockListChart.html

Widget Manager – Widget Instance

image 13

Title

Stock Ticker 1

WidgetProperties

Stocklist – Property Value

MSFT,AAPL,ATVI,AMZN,GOOG

WidgetOptions

View 1

Display View

Checked

Selected View

Selected

View 2

Display View

Checked

Selected View

Selected

Widget Manager - Widget Snippet

image 14

Widget Manager – Change the View and Property Value

In your Digital Workplace Site, click on the Akumina Icon in the Rail, click on the pencil, then click on your StockTickerWidget to bring up the Widget Manager. Change the view to View 2. Add TSLA to the stocklist. Click Update. The new view will be showing daily charts for all of the stocks and the TSLA stock info will now appear

Adding to the Dashboard

How to Deploy

  1. In the Management Apps Tab of AppManager, click on the Dashboard Widget Manager. Then Click Add New. Add the instance of the StockTickerWidget we just created. Use the Dashboard Widget Manager for reference. Click Save & Exit
  2. Navigate to the Dashboard.aspx page of your site. Click Customize, check StockTickerDashboard. Click Save.
  3. Flush your cache by clicking on the Akumina icon in the left rail, clicking the refresh icon, then clicking “Refresh All Cache”
  4. Refresh the page. You will see your StockTickerWidget

Dashboard

image 15

Title

StockTickerDashboard

Widget Instance

Stock Ticker 1

IsEnabled

Checked

Screenshots

image 16 image 17

Handlebars Example

For the Handlebars version of this example, please see Building A Custom Widget: Stock Ticker Widget

References

For more info on Custom Widgets see the following articles

⚠️ **GitHub.com Fallback** ⚠️