How to use my own AngularJS controllers with 3.0.1 dashboards?
-
I need to export point data in xlsx form and would rather not meddle with excel-reports due to only being able to have one report in the free version of the module. For this I planned to use something like in this example
http://jsfiddle.net/TheSharpieOne/XNVj3/1/
However, I'm facing problems when trying to get any of my own angular functions work. This is how I tried to test things out:
In my HTML file:
<div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="test()">Push me</md-button> </div> <script src="export.js"></script>
In my .JS file
var testing = angular.module('testing', []); testing.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); } }]);
I'm getting a reference error stating that angular is not defined. So should I have the reference in my export.js file? Or is there a mango file in which I should include my own controllers?
-
Hi Nyoa,
At first glance the code looks OK. But if you are getting the error saying angular is not defined then it must have something to do with angular not getting loaded properly into your JS file.
Could you please attach your complete JS and HTML file so I can help debug.
Thanks
Will -
Thank you for a fast reply!
Here is my complete HTML file called index.html
<!DOCTYPE html> <html lang="en" ma-app="maMaterialDashboards"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>JAMK Fosfaattianalysaattori</title> <link rel="icon" href="/images/favicon.ico"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="tyylit.css"> <link rel="stylesheet" href="/resources/angular-csp.css"></link> <link rel="stylesheet" href="../vendor/angular-material/angular-material.css"> <link rel="stylesheet" href="../vendor/material-design-icons/iconfont/material-icons.css"> <link rel="stylesheet" href="../vendor/mdPickers/mdPickers.css"> </head> <body layout="column"> <div ng-if="appLoading"> <img src="loader.gif" alt="App loading.." style="margin-left:50%;margin-top:25%"> </div> <div id="maincontainer" ng-cloak> <header> <img src="jamkfi_tunnus_sininen_suomi.png" alt="jamk.fi" style="width:50%;height:50%;margin-left:25%;"> </header> <div id="textContainer"> <img src="header.jpg" alt="Fosfaattifosfori PO4-P [mg/l]" style="width:50%;height:50%;margin-left:25%;"> </div> <div> <ma-get-point-value point-xid="DP_355369" point="point1"></ma-get-point-value> <ma-point-values id="testi" point="point1" values="point1Values" from="from" to="to" rollup="AVERAGE" rollup-interval="1 minutes"> </ma-point-values> <ma-serial-chart id="chartti" style="height: 500px; width: 100%" series-1-values="point1Values" series-1-point="point1" options="{chartCursor:{categoryBalloonDateFormat:'YYYY-MM-DD HH:NN'}, chartScrollbar:{oppositeAxis: false, scrollbarHeight: 40,offset: 25, graph:'DP_355369',updateOnReleaseOnly: true}}"> </ma-serial-chart> <div layout="row"> <md-input-container flex="33" class="no-errors-spacer"> <label>Date preset</label> <ma-date-range-picker from="from" to="to" preset="LAST_1_DAYS" update-interval="1 minutes"></ma-date-range-picker> </md-input-container> <md-input-container flex="33" class="no-errors-spacer"> <label>From date</label> <ma-date-picker ng-model="from"></ma-date-picker> </md-input-container> <md-input-container flex="33" class="no-errors-spacer"> <label>To date</label> <ma-date-picker ng-model="to"></ma-date-picker> </md-input-container> </div> <div> <div> <md-button class="md-raised" ng-click="showStats=true;showData=false" ng-hide="showStats">Statistics</md-button> <md-button class="md-raised" ng-click="showStats=false;showData=false" ng-show="showStats">Statistics</md-button> <md-button class="md-raised" ng-click="showData=true;showStats=false" ng-hide="showData">Data</md-button> <md-button class="md-raised" ng-click="showData=false;showStats=false" ng-show="showData">Data</md-button> </div> <div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="test()">Push me</md-button> </div> <div layout="row" ng-show="showStats" class="ng-hide"> <ma-point-statistics point="point1" from="from" to="to" statistics="statsObj"></ma-point-statistics> <ma-statistics-table id="statsTable" statistics="statsObj"></ma-statistics-table> </div> <div layout="row" ng-show="showData" class="ng-hide"> <table width="100%" height="500px"> <thead> <tr> <th>Value</th> <th>Time</th> </tr> </thead> <tbody> <tr ng-repeat="item in point1Values"> <td>{{item.value}}</td> <td>{{item.timestamp | moment:'format':'lll' }}</td> </tr> </tbody> </table> </div> </div> </div> </div> <script src="export.js"></script> <script src="/resources/require.js"></script> <script src="/resources/loaderConfig.js"></script> <script src="../js/loaderConfig.js"></script> <script type="text/javascript">require(['mango-3.0/bootstrap']);</script> </body> </html>
And here is my .js file called export.js. Right now it only has this one test function.
var testing = angular.module('testing', []); testing.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); } }]);
-
So basically for what you are trying to do, which is extend a mango dashboard app with your own logic you will want to start with the extendApp template. I'm sorry I know it is a bit confusing but here are the steps:
Start with the Extend app template and paste in your custom HTML that you have started on:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>My Custom App</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/resources/angular-csp.css"></link> <link rel="stylesheet" href="../vendor/angular-material/angular-material.css"> <link rel="stylesheet" href="../vendor/material-design-icons/iconfont/material-icons.css"> </head> <body layout="column"> <div ng-if="appLoading"> <span>App is loading..</span> </div> <div id="maincontainer" ng-cloak>........YOUR HTML.......</div> <script src="/resources/require.js"></script> <script src="/resources/loaderConfig.js"></script> <script src="../js/loaderConfig.js"></script> <script type="text/javascript">require(['dashboards/templates/extendApp']);</script> </body> </html>
Add your custom css file and the mdPickers CSS ref to the head which is missing from the template (a bug we need to add it to this template for datepickers):
<link rel="stylesheet" type="text/css" href="tyylit.css"> <link rel="stylesheet" href="../vendor/mdPickers/mdPickers.css">
See that require JS command at the bottom? This is what your will need to update to your custom JS file. So if your export.js and index.html is in a folder called custom you will reference it like (the .js is left out when using require):
<script type="text/javascript">require(['dashboards/custom/export']);</script>
Now you will need to update the export.js to use the JS portion of the extendApp template.
(http://localhost:8080/modules/dashboards/web/mdAdmin/#/dashboard/examples/templates/extend-app)/** * @copyright 2016 {@link http://infiniteautomation.com|Infinite Automation Systems, Inc.} All rights reserved. * @author Jared Wiltshire */ define([ 'angular', 'mango-3.0/maMaterialDashboards' ], function(angular, maMaterialDashboards) { 'use strict'; var myApp = angular.module('myApp', ['maMaterialDashboards']); myApp.run(['$rootScope', function($rootScope) { $rootScope.pi = function() { return Math.PI; } }]); myApp.directive('myCustomComponent', function() { return { restrict: 'E', scope: { name: '@' }, template: '<span>Hello {{name}}!</span>' }; }); angular.element(document).ready(function() { angular.bootstrap(document.documentElement, ['myApp']); }); }); // define
you should now be able to define your controller on the myApp module. So below the directive definition block add:
myApp.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); } }]);
The function defined in the controller should now be available to use within your <div ng-controller="myCtrl">...</div>
There is also a directive definition template in the JS file that you can use to create your own HTML directives that you would use like <my-custom-component></my-custom-component> (camel case in JS directive definition > dash lowercase in html)
If you still have issues please update the post with complete HTML / JS files.
Cheers
Will -
Thank you for your help so far. Should my .js file look like this with the added custom function? I'm getting ReferenceError: $scope is not defined
/** * @copyright 2016 {@link http://infiniteautomation.com|Infinite Automation Systems, Inc.} All rights reserved. * @author Jared Wiltshire */ define([ 'angular', 'mango-3.0/maMaterialDashboards' ], function(angular, maMaterialDashboards) { 'use strict'; var myApp = angular.module('myApp', ['maMaterialDashboards']); myApp.run(['$rootScope', function($rootScope) { $rootScope.pi = function() { return Math.PI; } }]); myApp.directive('myCustomComponent', function() { return { restrict: 'E', scope: { name: '@' }, template: '<span>Hello {{name}}!</span>' }; }); myApp.controller('myCtrl',[$scope, function ($scope) { $scope.test = function(){ console.log('Logg meh'); }; }]); angular.element(document).ready(function() { angular.bootstrap(document.documentElement, ['myApp']); }); }); // define
Here is the HTML file just in case. I changed it to the template file because i thought it would be a lot easier to troubleshoot in case it was needed. The main thing I need right now in any case is to get the custom functions work before actually adding them to my dashboard
<!DOCTYPE html> <html lang="en" ma-app="maMaterialDashboards"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <title>My Custom App</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/resources/angular-csp.css"></link> <link rel="stylesheet" href="../vendor/angular-material/angular-material.css"> <link rel="stylesheet" href="../vendor/material-design-icons/iconfont/material-icons.css"> <link rel="stylesheet" href="../vendor/mdPickers/mdPickers.css"> </head> <body layout="column"> <div ng-if="appLoading"> <span>App is loading..</span> </div> <div ng-cloak layout="column" flex> <!-- Your content here --> <span>Pi is {{pi() | number:5}}.</span> <my-custom-component name="John Smith"><my-custom-component> </div> <div ng-controller="myCtrl"> <md-button class="md-raised" ng-click="test()">Push me</md-button> </div> <script src="/resources/require.js"></script> <script src="/resources/loaderConfig.js"></script> <script src="../js/loaderConfig.js"></script> <script type="text/javascript">require(['dashboards/fosfaattifosfori/export']);</script> </body> </html>
Thanks a lot for your help!
-
You're missing the single quotes around $scope. See below.
myApp.controller('myCtrl',['$scope', function ($scope) { $scope.test = function(){ console.log('Logg meh'); }; }]);
The scope variable is injected into your controller using Angular's dependency injection. Have a look here for more information on the syntax.
-
I finally got it to work. Thank you a lot, this would have been quite a bit harder for me to achieve without your fast and accurate help!