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

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.

Related

How to fix 'undefined' error with $scope.detailsForm

I am new to angularjs and have written a small program but facing the error "scope.detailsForm" as undefined. Could someone help me what is the issue with the below code.
b.js file:
var app = angular.module('my-app', []);
app.controller("my-cont", function($scope) {
$scope.detailsForm.clickme.$setValidity("error1",true);
});
b.html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script type="text/javascript" src="b.js"></script>
</head>
<body ng-app="my-app" ng-controller="my-cont">
<form method="get" name="detailsForm" ng-model="detailsForm">
<button name='clickme' ng-disabled="detailsForm.clickme.$error.error1">Click Me!</button>
</form>
</body>
</html>
Your problem is that you can not get it when the controller is not built, you need to wait for the html to be processed by Angular. Here's an example.
As you'll see in the console, the first log will echo undefined, and the second will echo the form.
var app = angular.module('MyApp', []);
app.controller("MyCont", ['$scope', function($scope) {
console.log($scope.detailsForm);
$scope.onClicked = function()
{
console.log($scope.detailsForm);
}
}]);

Argument 'MyController' is not a function, got undefined: differences between Edge browser and Firefox / Chrome on Angularjs

I am learning AngularJS following the code samples in ng-book.
I have the following folder structure under the app root folder
../css
../img
../lib
../lib/angular
../js
../partials
I have angular 1.2.11 installed in the lib/angular directory (yes I know this is not the latest version..)
The following code works fine in Firefox (41.0.1) but in Chrome (45.0.2454.101 m), Edge and IE (11.0.22) I get an error message
"Argument 'MyController' is not a function, got undefined"
Code follows:
index.html in root folder:
<!doctype html>
<html lang="en" ng-app>
<head>
<meta charset="utf-8">
<title>My AngularJS App</title>
<link rel="stylesheet" href="css/app.css"/>
</head>
<body>
<div>
{{1+1}}
</div>
<div ng-controller="MyController">
{{name}}<br/> {{clock}}
</div>
<script src="lib/angular/angular.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
in app.js in the js folder:
function MyController($scope) {
$scope.name = "in sub";
$scope.clock = new Date();
console.log = "Active";
var updateClock = function () {
$scope.clock = new Date();
};
setInterval(function () {
$scope.$apply(updateClock);
}, 1000);
updateClock();
};
If I put the app.js into the root folder it still does not work so it is not path related.
If I put the code into an inline script then it works so I don't think it is an issue with the code. Why does this work in one browser but not the others. For reference i am calling this directly from the file browser, not via http.
file:///C:/Users/aaron_000/Desktop/Programming/Angular/app/index.html
If I upgrade to a later version of angular does the problem go away?
I know that this is not the 'proper' way to construct an Angular app, but I am taking it one component at a time :)
Look js/app.js is right. Works fine for me.
var app = angular.module("App", []);
app.controller('AppController', function MyController($scope) {
$scope.name = "in sub";
$scope.clock = new Date();
console.log = "Active";
var updateClock = function() {
$scope.clock = new Date();
};
setInterval(function() {
$scope.$apply(updateClock);
}, 1000);
updateClock();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.11/angular.min.js"></script>
<!doctype html>
<html lang="en" ng-app="App">
<head>
<meta charset="utf-8">
<title>My AngularJS App</title>
</head>
<body>
<div>
{{1+1}}
</div>
<div ng-controller="AppController">
{{name}}
<br/>{{clock}}
</div>
</body>
</html>

How to update controller variable with 'ng-model' AngularJS?

I am trying to get user input through a text box using ng-model, and append to a base URL for a http.get call as follow;
index.html:
<html ng-app='vidRoute'>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Search Video</title>
<link rel="stylesheet" href="app/css/custom/main.css">
<link rel="stylesheet" href="app/css/custom/responsive.css">
</head>
<body>
<div id='mainwrapper'>
<div id='header' ng-controller="searchController">
<input type="text" id="searchTxt" ng-model="append">
Search Video
</div>
<div id="poster">
<div ng-view></div>
</div>
</div>
<script type="text/javascript" src="app/javascript/vendor/jquery-2.1.1.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-route.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-resource.js"></script>
<script type="text/javascript" src="app/javascript/vendor/angular-mocks.js"></script>
<script type="text/javascript" src="app/javascript/custom/searchcontroller.js"></script>
<script type="text/javascript" src="app/javascript/custom/vidRoute.js"></script>
</body>
</html>
searchcontroller.js
'use strict';
var vidcontrol = angular.module("vidcontrol", []);
vidcontrol.controller("vidcontroller", ['$scope', '$http', function($scope, $http) {
$http.get('http://api.themoviedb.org/3/tv/airing_today?api_key=d5e87524383e2872a9555990b268dc5b').success(function(response) {
$scope.results = response.results;
});
}]);
vidcontrol.controller('searchController', ['$scope', '$http',
function ($scope, $http) {
var url = "http://api.themoviedb.org/3/search/movie?api_key=d5e87524383e2872a9555990b268dc5b&query=";
// var searchTxt = $('#searchTxt').val();// this works fine when used
var searchUrl = url + append; //$scope.append also logs 'undefined' on the console
$http.get(searchUrl).success(function (response) {
$scope.searchResults = response.results;
});
}]);
but I'm not getting any response. when I log searchUrl on console, I could see that append was not updated according to value from text box. I'm quite new to Angular and I can't figure out what I'm doing wrong. What should I do to fix this?
Now, I see the issue. When controller loaded, it executes controller code. That mean REST query runs before view is built. That is reason you see undefined problem. Solution is to define a method in controller which will be invoked when you click "Search Video".
Update view
Search Video //Look at ng-click
Update Controller:
vidcontrol.controller('searchController', ['$scope', '$http',function($scope, $http) {
var url = "http://api.themoviedb.org/3/search/movie?api_key=d5e87524383e2872a9555990b268dc5b&query=";
$scope.search = function(){ // Look at here, Defined a method to invoke on "Search Video" link click
var searchUrl = url + $scope.append;
$http.get(searchUrl).success(function(response) {
$scope.searchResults = response.results;
});
};
} ]);

Call dart function in angular controller initialization

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.

angularjs $watch is not working

I have written this code to watch changes in password field,
My code is
var Controllers = angular.module('myapp');
Controllers.controller('SignUpCtrl', function ($scope,$http,$location) {
$scope.$watch($scope.password, validatePasswordFun);
function validatePasswordFun(newValue,oldValue,scope){
console.debug("Test");
}
});
But problem that i am facing is :
on page load, it prints "test" in firebug console,
After that if i enter text/password in password field, it does not execute the function.
You are watching in wrong way it should be string value like
var Controllers = angular.module('myapp');
Controllers.controller('SignUpCtrl', function ($scope,$http,$location) {
$scope.$watch('password', validatePasswordFun);
function validatePasswordFun(newValue,oldValue,scope){
console.debug("Test");
}
});
Internally watch is using $parse service available which expects the property name so you wrap inside a string 'password' so that $parse could work properly
--edit working html
<!DOCTYPE html>
<html ng-app="Demo" >
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"></script>
</head>
<body ng-controller="test" >
<input type="password" ng-model="password" />
<script>
var app = angular.module('Demo', []);
function test($scope) {
$scope.$watch('password', function (newvalue, oldvalue) {
alert(newvalue);
});
}
</script>
</body>
</html>

Resources