Call dart function in angular controller initialization - angularjs

I try to call a dart function in an AngularJS controller initialization, but I get ReferenceError: myFunction is not defined.
index.dart
import 'dart:js';
myDartFunction() {
return 42;
}
main() {
context['myFunction'] = (JsObject exchange) {
exchange['output'] = myDartFunction();
};
}
My html with AngularJS:
<!DOCTYPE html>
<html ng-app="MyApp">
<head lang="en">
<meta charset="UTF-8">
<title>My Title</title>
</head>
<body>
<div ng-controller="MyCtrl">
<p>{{var}}</p>
</div>
<script type="application/dart" src="index.dart"></script>
<script type="application/javascript" src="../packages/browser/dart.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script>
angular.module("MyApp", []).controller('MyCtrl', function($scope) {
var exchange = {};
myFunction(exchange);
$scope.var = exchange['output'];
});
</script>
</body>
</html>
It seems to me, that context['myFunction'] has not been set yet, when controller gets initialized. How can I wait for it and initialize $scope.var?

I found out, that it is possible to use window.onload, which is called after my dart function has been exported to JS. Then I use $scope.$apply to change my scope variable.
angular.module("MyApp", []).controller('MyCtrl', function($scope) {
window.onload = function () {
$scope.$apply(function () {
var exchange = {};
myFunction(exchange);
$scope.var = exchange['output'];
});
}
});

I would suggest to fire an event from Dart after the function was created and execute the code in JavaScript as event handler for this event.

Related

pass data to angular controller from a global function

See example below and the TODO in the send function : How can I assign the label value in the global send function to dropboxController dropbox.label
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.0-beta.4/angular.min.js"></script>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css" />
<script type="text/javascript">
window.onload=function() {
$('#AddIn').append("<div ng-app='dropboxApp' ng-controller='dropboxController as dropbox'>{{dropbox.label}}</div>");
angular.module('dropboxApp', [])
.controller('dropboxController', function () {
var dropbox = this;
dropbox.label = "hello angular";
});
angular.bootstrap($('#AddIn'), ['dropboxApp']);
}
function send(label)
{
//TODO assign label value to dropboxController dropbox.label
}
</script>
</head>
<body>
<div id="AddIn"></div>
<button onclick="send('new label');">Send</button>
</body>
</html>
Use angular.element and get scope of specific dom element and apply label to it.
Change dropbox.label to $scope.label and inject $scope in controller because this and $scope are different. Check 'this' vs $scope in AngularJS controllers
Keep in Mind: Here I have used myDiv which has scope for angular and added id in append div line.
It's better to use ng-click instead of onclick if possible.
window.onload = function() {
$('#AddIn').append("<div id='myDiv' ng-app='dropboxApp' ng-controller='dropboxController as dropbox'>{{label}}</div>");
angular.module('dropboxApp', [])
.controller('dropboxController', function($scope) {
var dropbox = this;
$scope.label = "hello angular";
});
angular.bootstrap($('#AddIn'), ['dropboxApp']);
}
function send(label) {
var scope = angular.element($("#myDiv")).scope();
scope.$apply(function() {
scope.label = label;
})
console.log(scope.label);
}
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.0-beta.4/angular.min.js"></script>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
</head>
<body>
<div id="AddIn"></div>
<button id="myButton" onclick="send('new label');">Send</button>
</body>
</html>

initialize angular on window.onload

How can i make my angular app work when running the angular initialisation code in the window onload event
PS : the code in comment works, the code in the onload event doesn't...
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.0-beta.4/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<!--script>
angular.module('dropboxApp', [])
.controller('dropboxController', function () {
var dropbox = this;
dropbox.label = 'hello angular';
});
</script-->
<script type="text/javascript">
window.onload=function() {
angular.module('dropboxApp', [])
.controller('dropboxController', function () {
var dropbox = this;
dropbox.label = 'hello angular';
});}
</script>
</head>
<body>
<div ng-app="dropboxApp" ng-controller="dropboxController as dropbox">
{{dropbox.label}}
</div>
</body>
</html>
Please take a look on my fix for your example in IIFE style:
jsfiddle
<script>
window.onload=(function (angular) {
angular.module('dropboxApp', [])
.controller('dropboxController', function () {
var dropbox = this;
dropbox.label = 'hello angular';
});})(window.angular);
</script>
But I really really really don't suggest you to use window.onload for this purposes. It's really better to use ng-init. And if you're worried about some content, which isn't loaded until page is ready, you can use ng-cloak

Angularjs controller not working defined in a self invoking function hooked to a module

I have a page as follows. The controller is not working. Can someone please suggest me whats wrong?
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" data-ng-app="demoApp">
<head>
<title>AnjularJs Hello World</title>
</head>
<body data-ng-controller="CustomerController">
<h2>Customers</h2>
<div id="Trial">{{name}}</div>
<script src="Scripts/angular.js"></script>
<script>
(function () {
alert("Inside Self invoking function. This is popping up.");
CustomerController = function ($scope) {
alert("Inside controller. But this is NOT popping up");
$scope.name = 'HeHe';
};
CustomerController.$inject = ['$scope'];
angular.module('demoApp').controller('CustomerController', CustomerController);
}());
</script>
</body>
</html>
Alert inside the controller is not popping. The first alert is popping. Also the div with id="Trial" is not printing the name.
What am I missing?
You never create your demoApp-module. With angular.module(name) you get an already created module, with angular.module(name, dependencies) you set(create) a module. So simply add:
angular.module('demoApp', []);
above the line with angular.module('demoApp') and your cord works just fine:
(function () {
alert("Inside Self invoking function. This is popping up.");
CustomerController = function ($scope) {
alert("Inside controller. But this is NOT popping up");
$scope.name = 'HeHe';
};
CustomerController.$inject = ['$scope'];
angular.module('demoApp', []);
angular.module('demoApp').controller('CustomerController', CustomerController);
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="demoApp" data-ng-controller="CustomerController">
<h2>Customers</h2>
<div id="Trial">{{name}}</div>
</body>

Office.js getFilePropertiesAsync fails on second call in Angular.js

I have an Office Task Pane App written with Office Javascript API (Office.js) that calls Office.context.document.getFilePropertiesAsync and places the returned URL in an angular variable:
$scope.getDocumentUrl = function () {
Office.context.document.getFilePropertiesAsync(function (asyncResult) {
$scope.url = asyncResult.value.url;
});
};
I then have a button that calls this. This works file the first time, but when I press the button a second time, it never enters the callback and displays this error:
TypeError: Object expected at verifyAndExtractCall
(https://localhost:44304/scripts/office/1.1/o15apptofilemappingtable.js:11:54588)
at Anonymous function
(https://localhost:44304/scripts/office/1.1/o15apptofilemappingtable.js:11:83048)
at Anonymous function
(https://localhost:44304/scripts/office/1.1/o15apptofilemappingtable.js:11:86071)
at $scope.getDocumentUrl
(https://localhost:44304/AngularJs/controllers/sandpit.controller.js:130:6)
at $parseFunctionCall
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:12403:7)
at callback
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:21566:17)
at Scope.prototype.$eval
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:14466:9)
at Scope.prototype.$apply
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:14565:11)
at Anonymous function
(https://localhost:44304/AngularJs/bower_components/angular/angular.js:21571:17)
at jQuery.event.dispatch (https://localhos
This is a simplified version of another situation that creates the same error. It also happens with getFileAsync. I know I need $scope.$apply to display the change. I know you can get the URL in other ways. I need to know the cause of the error.
I test your scenario in my local machine. I could not repro your issue.
My simple test app has two files: AngularTest.html and AngularTest.js.
Content in AngularTest.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title></title>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
<script src="//ajax.microsoft.com/ajax/4.0/1/MicrosoftAjax.js" type="text/javascript"></script>
<script src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js" type="text/javascript"></script>
<script src="AngularTest.js" type="text/javascript"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="getDocumentUrl()">Get Url!</button>
Url is: {{url}}
</div>
</body>
</html>
Content in AngularTest.js:
(function () {
"use strict";
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.url = "";
$scope.getDocumentUrl = function () {
Office.context.document.getFilePropertiesAsync(function (asyncResult) {
$scope.url = asyncResult.value.url;
});
};
});
Office.initialize = function (reason) {
};
})();
You can obtain the URL by clicking the button "Get Url". I tested it in Excel 2013 SP 1.

angular and socket.io - wrong code structure

I'm quite new with Node/Angular/.. and tried this simple script. But it doesn't work, whats wrong with it?
I always get Error: [ng:areq] http://errors.angularjs.org/1.3.0/ng/areq?p0=rCtlr&p1=not%20a%20function%2C%20got%20undefined
<!DOCTYPE html>
<html ng-app>
<head lang="en">
<meta charset="UTF-8">
<title>test</title>
<script src="lib/angular/1.3.0/angular.min.js"></script>
<script src="lib/socket.io/1.2.0/socket.io.js"></script>
</head>
<body ng-controller="rCtlr">
<h1>{{xTime}}</h1>
<script>
function rCtlr($scope){
var socket = io.connect();
socket.on('updateTime', function (data) {
$scope.xTime = data.updateTime;
console.log(data);
});
}
</script>
</body>
</html>
Without Angular it works fine, I guess there is an issue with the function scope?
Thanks for help!
To make it work properly you should:
1) Add name to your ng-app:
<html ng-app="myapp"> //myapp is an example name
2) Then you can define angular module and controller like this:
angular.module("myapp",[]) // define module with name from ng-app
.controller('rCtlr',['$scope', function($scope){ //define controller for your module
var socket = io.connect();
socket.on('updateTime', function (data) {
$scope.xTime = data.updateTime;
console.log(data);
});
}]);
alternatively (it does the same):
var app = angular.module("myapp",[]);
app.controller('rCtlr',['$scope', function($scope){
//controller body
}]);
PS. It doesn't matter, but name of you controller should be "rCtrl" rather than "rCtlr"
Here is a refference to angular docs: https://docs.angularjs.org/guide/controller
Update, thanks to MarkS: But .. see comment to Mark's answer
<!DOCTYPE html>
<html >
<head lang="en">
<meta charset="UTF-8">
<title>AngularSocket</title>
<script src="lib/angular/1.3.0/angular.min.js" type="text/javascript"></script>
<script src="lib/socket.io/1.2.0/socket.io.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
</head>
<body data-ng-app="angApp">
<div data-ng-controller="timeCtrl">
<h1>{{xTime}}</h1>
</div>
</body>
</html>
app.js:
angular
.module('angApp', [])
.controller('timeCtrl', ['$scope', function($scope) {
var socket = io.connect();
socket.on('updateTime', function (data) {
$scope.xTime = data.updateTime;
console.log(data);
});
}]);

Resources