$http.get succeeds; but can't access output? - javascript

How do I get the output from my remote server? - Firebug confirms that the JSON output is correct.
Here is my attempt, I have tried to be as standard as possible (Plnkr):
app.js, controllers.js, factories.js
'use strict';
var nameVersionFactory = angular.module('name.factories.version', []);
nameVersionFactory.factory('Version', ['$q', '$http', function ($q, $http) {
var d = $q.defer();
$http.get('/api').then(function (response) {
d.resolve(response);
});
return d.promise;
}]);
var nameVerCtrl = angular.module('name.controllers.version',
['name.factories.version']);
nameVerCtrl.controller(
'verCtrl', ['$scope', 'Version', function ($scope, Version) {
$scope.version = Version; /* {'status': 'online',
'rest_api_version': '1.1.14',
'server_time': '…'} */
}]
);
var nameApp = angular.module('name', ['name.controllers.version']);
/* CORS */
nameApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
Python REST API (30 lines): https://gist.github.com/anonymous/7d34867aca543911a06f
index.html
<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="name" lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<div data-ng-controller="verCtrl">
<pre>{{version | json}}</pre>
<pre>{{version.status}}</pre>
<pre>{{version.data | json}}</pre>
<pre>{{version.data.status}}</pre>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js">
</script>
<script src="scripts/controllers.js"></script>
<script src="scripts/factories.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>
Unfortunately I get no JSON output within those <pre>…</pre> tags.

Promises are no longer unwrapped automatically by scope variables in Angular 1.2+.
So, you have to do:
Version().then(function(result){
$scope.version = result;
});
Moreover, $http returns promises already, so this:
var d = $q.defer();
$http.get('/api').then(function (response) {
d.resolve(response);
});
return d.promise;
Can simply become:
return $http.get("/api");

Related

AngularJS call compile after compiled

<!DOCTYPE HTML>
<html lang="en-US" ng-app="theapp">
<head>
<meta charset="UTF-8">
<title>asd</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script type="text/javascript">
var mainScope;
angular.module('theapp', []).controller('MainCtrl', function($scope, $injector) {
$scope.demo = "test123";
$scope.scopecomp = function(){
angular.element(document).injector().invoke(function ($compile) {
$compile(document.body)($scope);
});
}
mainScope = $scope;
});
function addDiv(){
var $newDiv = $('<div>{{demo}}</div>');
$(document.body).append($newDiv);
}
function comp(){
mainScope.comp();
}
</script>
</head>
<body ng-controller="MainCtrl" ng-change="comp();">
<h1>{{demo}}</h1>
<input type="text" id="compText" />
<button onclick="addDiv();">add</button>
<button ng-click="scopecomp();">compile with ng-click (works fine)</button>
<button onclick="comp();">compile with onlick (not working)</button>
</body>
</html>
I want to run the comp() function anywhere in my project. I tried button onclick,it didn't work but ng-click works fine. What is the problem ? Why onclick doesn't work ?
New : changeContent function added.
<!DOCTYPE HTML>
<html lang="en-US" ng-app="theapp">
<head ng-controller="MainCtrl as main">
<meta charset="UTF-8">
<title>asd</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script type="text/javascript">
angular.module("theapp", []).controller("MainCtrl", MainController);
MainController.$injector = ['$timeout'];
var vm;
function MainController($timeout) {
vm = this;
vm.post = null;
function loadStuff(){
$timeout(function() {
vm.post = {
title: "Post Title",
content: "Post Content"
};
}, 1000);
}
loadStuff();
}
function changeContent(){
vm.post.content = "<div>new content </div>";
}
</script>
</head>
<body ng-controller="MainCtrl as main">
<p ng-hide="main.post">Loading...</p>
<h3>{{main.post.title}}</h3>
<p>{{main.post.content}}</p>
<button onclick="changeContent();">change</button>
</body>
</html>
New bodyController()
function bodyController($scope, $injector) {
_bodyController = this;
$scope.title = "ttt";
$scope.content = "aaa";
$scope.comp = function(){
angular.element(document).injector().invoke(function ($compile) {
$compile(document.body)($scope);
});
}
myAPP.Run(function(){
$scope.title = globalOBJ.title;
$scope.content = globalOBJ.content;
$scope.comp();
});
}
You should change your '' to this:
<body ng-controller="MainCtrl" ng-model="demo" ng-change="comp();">
If you check the url from the first line of the error log: https://docs.angularjs.org/error/$compile/ctreq?p0=ngModel&p1=ngChange. The problem is explained:
Controller 'ngModel', required by directive 'ngChange', can't be
found! Description This error occurs when HTML compiler tries to
process a directive that specifies the require option in a directive
definition, but the required directive controller is not present on
the current DOM element (or its ancestor element, if ^ was specified).
To resolve this error ensure that there is no typo in the required
controller name and that the required directive controller is present
on the current element.
The directive 'ng-change' require a 'ng-model' to work properly, that is why you are getting an compile error.
Now your second question, "Why onclick doesn't work ?". You should never manipulate the DOM from the controller, if you have to do that use a directive. When you call "scopecomp()" from the ng-click that method is invoked from "within" the angular engine, it will fire an digest cycle which will process the "html" (it's more than that, I'm trying to keep it simple) and print what you expect, but when you add "{{demo}}" directly to the DOM, that variable will not be processed.
There is no need to change the DOM manually to do what you are looking for, check the snippet below. I simulated your "database request" with a timeout function.
angular.module("app", [])
.controller("MainController", MainController);
MainController.$injector = ['$timeout'];
function MainController($timeout) {
var vm = this;
vm.post = null;
function loadStuff() {
$timeout(function() {
vm.post = {
title: "Post Title",
content: "Post Content"
};
}, 1000);
}
loadStuff();
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MainController as main">
<p ng-hide="main.post">Loading...</p>
<h3>{{main.post.title}}</h3>
<p>{{main.post.content}}</p>
</div>
$FirebaseJS.Run(function(){
$scope.$apply(function(){
$scope.obj = globalOBJ;
});
});
Finally I got it.

AngularJS: help registering custom service the right way

Newbie Question
Have been watching this great Angular Beginners course but got stuck in the register process.
Code project (plnkr.co)
index.html
<!DOCTYPE html>
<html ng-app="githubViewer">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script src="github.js"></script>
</head>
<body ng-controller="MainController">
<h1>{{message}}</h1>
{{ countdown }}
<form name="searchUser" ng-submit="search(username)">
<input type="search" required placeholder="Username to find" ng-model="username"/>
<input type="submit" value="Search">
</form>
<div ng-include="'userdetails.html'" ng-show="user"> </div>
</body>
</html>
github.js
(function() {
var github = function($http) { // requires the service $http
// Private implementation details //
var gettingUser = function(username) {
return $http.get("https://api.github.com/users/" + username)
.then(function(response) {
return response.data;
});
/* returning the promise that already comes with
the function to perform the data extration
*/
};
var gettingRepos = function(user) {
return $http.get(user.repos_url)
.then(function(response) {
return response.data;
});
/* returning a promise that it will return the data
- so the controller doesn't have to. */
};
// Public API //
return {
gettingUser: gettingUser,
gettingRepos: gettingRepos
};
// returns an object (github service)
};
var module = angular.module("githubViewer");
/* Not creating a module, just getting the reference
to the one created in script.js So no need to list
the dependencies in a list after githubViewer*/
// Register the Service
module.factory("$github", github);
}());
script.js
(function() {
var app = angular.module("githubViewer", []);
var MainController = function(
$scope, $github, $interval, $log,
$anchorScroll, $location) {
var onUserComplete = function(data) {
$scope.user = data;
$github.gettingRepos($scope.user)
.then(onRepos, onError);
};
var onRepos = function(data){
$scope.repos = data;
$anchorScroll( $location.hash("userDetails") );
}
var onError = function(reason) {
$scope.error = "Could not fetch data";
};
var decrementCountdown = function(){
$scope.countdown -= 1;
if($scope.countdown < 1){
$scope.search($scope.username);
}
}
$scope.search = function(username) {
$log.info("Searching for "+ username);
$github.gettingUser(username).then(onUserComplete, onError);
if(countdownIntervalObj){
$interval.cancel(countdownIntervalObj);
$scope.countdown = null;
}
};
var countdownInterval = null;
var startCountdown = function(){
countdownIntervalObj = $interval(decrementCountdown, 1000, $scope.countdown);
}
$scope.username = "angular";
$scope.message = "GitHub Viewer";
$scope.repoSortOrder = "-stargazers_count";
$scope.countdown = 5;
startCountdown();
};
app.controller("MainController",
["$scope", "$http", "$interval", "$log", "$anchorScroll", "$location", "$github", MainController]);
}());
The console keeps saying that the $github.gettingUser is not a function. What am I doing wrong?
Watch out for the order when you inject your dependencies as you are injecting seven but just passing six to the controller in the wrong order. You need to pass $http and put $github at the end.
var MainController = function($scope, $http, $interval, $log, $anchorScroll, $location, $github)
app.controller("MainController", ["$scope", "$http", "$interval", "$log", "$anchorScroll", "$location", "$github", MainController]);
When you inject resources into your controller
app.controller("MainController", ["$scope", "$http", "$interval", "$log", "$anchorScroll", "$location", "$github", MainController]);
order et type must match your controller function declaration
var MainController = function(
$scope, $github, $interval, $log,
$anchorScroll, $location) {
So here what $github contains is the $http module :)
Here is a corrected version of your plunkr
http://plnkr.co/edit/9UyNHDKiXDZAZt8PPEPy?p=preview
However I prefer this syntax, I find it more clear: http://plnkr.co/edit/byhQ7ST8AZlQ6oMYIMeV?p=preview
You should take a look to https://github.com/johnpapa/angular-styleguide
A styleguide were using at work, filled with best practices.
Have fun with angular
because the order of providers are not the same in the array ["scope", "github", etc] with the controller's. your service corresponds to another provider which is minified, even if it is not, it does not matter. you have to pass the injectors in the same order you define in the provider array

Pass Javascript variable to AngularJS

I am new to AngularJS and JavaScript in general and need some help trying get a JavaScript variable into my AngularJS controller. Here is my html page:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" ng-app="test">
<head>
<meta charset="utf-8" />
<title>Test</title>
<!--Third party scripts-->
<script type="text/javascript" src="js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/angular-sanitize.min.js"></script>
<!--Custom scripts-->
<script type=" text/javascript" src="app/test.js"></script>
<!--Third party style sheets-->
<link type="text/css" rel="stylesheet" href="css/test.css" />
</head>
<body>
<div id="page" ng-controller="PageCtrl">
<ul>
<li ng-click="print(gBool)">Print</li>
</ul>
</div>
</body>
</html>
<script>
var gBool = false;
window.onload = function () {
gBool = true;
};
</script>
Here is the AngularJS code:
var app = angular.module('test', []);
app.controller('PageCtrl', ['$scope', function ($scope) {
$scope.print = function (boolParam) {
console.log(boolParam);
};
}]);
This just prints out 'undefined' in the console when it executes. Is this something that should work?
You need to do it in the "angular" way by using $window:
var app = angular.module('myapp', []);
app.controller('MainCtrl', ['$scope', '$window', function($scope, $window) {
$scope.memId = $window.memId;
}]);
In this line:
<li ng-click="print(gBool)">Print</li>
You are referencing a variable gBool in your scope, so its $scope.gBool
If you define in your JavaScript instead in your html, will work.
$scope.gBool = true;
Also, lookup $window and use it from your controller like this:
app.controller('PageCtrl', ['$scope', '$window', function ($scope, '$window') {
$scope.gBool = false;
$window.onload = function() {
$scope.gBool = true;
};
$scope.print = function (boolParam) {
console.log(boolParam);
};
}]);
There are two Things to focus
(i)You need to initialize the variable you can use the ng-init
(ii) Declare a function to assign the bool value initially
Here is the working Application

How do I turn a json array into a js array in AngularJs?

I'm starting out in Angular and front end development and can't seem to solve the following.
I have reassigned one variable to another: $scope.testarray = $scope.todos; but when using the Angular bindings, only the 'todos' will get displayed.
var App = angular.module('App', []);
App.controller('TodoCtrl', function($scope, $http) {
$http.get('todos.json')
.then(function(res){
$scope.todos = res.data;
});
$scope.testarray = $scope.todos;
});
and html:
<!doctype html>
<html ng-app="App" >
<head>
<meta charset="utf-8">
<title>Todos $http</title>
<link rel="stylesheet" href="style.css">
<script>document.write("<base href=\"" + document.location + "\" />"); </script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="TodoCtrl">
<ul>
<li ng-repeat="todo in todos">
{{todo.text}} - <em>{{todo.done}}</em>
</li>
</ul>
this doesn't display: {{testarray}}
</br></br>
but this does dislay: {{todos}}
</body>
</html>
In your code
App.controller('TodoCtrl', function($scope, $http) { $http.get('todos.json')
.then(function(res){
$scope.todos = res.data;
}); //.then block ends here
$scope.testarray = $scope.todos;
});
$scope.testarray = $scope.todos; is written outside of then block. $http.get is an asynchronous call, therefore, this line will be executed even before $scope.todos is defined.
Moving this inside .then block will solve your problem. Assuming $scope.testarray is declared here.
App.controller('TodoCtrl', function($scope, $http) {
$http.get('todos.json').then(function(res){
$scope.todos = res.data;
$scope.testarray = $scope.todos; //Moved inside
});
});
Comment if you need more help.
I would just use a $scope.$watch,
var App = angular.module('App', []);
App.controller('TodoCtrl', function($scope, $http) {
$http.get('todos.json')
.then(function(res){
$scope.todos = res.data;
});
$scope.testarray = $scope.todos;
$scope.$watch('todos', function(newValue, oldValue) {
$scope.testarray = newValue;
});
});

Angularjs - Binding between controller and view

I am having problem with Angularjs view. Somehow i am doing something wrong and don't know where is the problem. Hope someone can help me out.
The problem is {{user.login}} (userRepoInfo.html file) does not get called at all from the controller and if i do console.log it is coming through fine from services. I am definitely doing something wrong between view and controller
I have five files
1) gitHubApiServices.js
2) gitHubApiController.js
3) userRepoInfo.html
4) app.js
5) index.html
Below is gitHubApiServices.js
(function() {
var gitHubApiFactory = function($http) {
var factory = {};
factory.getUserName = function(userName) {
console.log(userName + " " + "This is from Services")
return $http.get("https://api.github.com/users/" + userName);
};
return factory;
};
gitHubApiFactory.$inject = ['$http'];
angular.module('gitHubApp').factory('gitHubApiFactory',gitHubApiFactory);
}());
Below is gitHubApiController.js
(function() {
var gitHubInfoController = function ($scope,gitHubApiFactory) {
$scope.user = null;
$scope.gitHubUser = function(userName) {
gitHubApiFactory.getUserName(userName)
.success(function (data) {
$scope.user = data;
console.log(data);
})
.error(function(data, status, headers, config) {
$log.log(data.error + ' ' + status);
});
}
};
gitHubInfoController.$inject = ['$scope','gitHubApiFactory'];
angular.module('gitHubApp')
.controller('gitHubInfoController', gitHubInfoController);
}());
Below is userRepoInfo.html
<div data-ng-controller="gitHubInfoController">
<h1>Github App</h1>
<input type="text" id="gitUserName" ng-model="gitUser" placeholder="Please enter your GitHub Username">
Get my Repository
{{user.login}}
</div>
Below is app.js
(function() {
var app = angular.module('gitHubApp', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'gitHubInfoController',
templateUrl: 'app/views/userRepoInfo.html'
})
.otherwise( { redirectTo: '/' } );
});
}());
Below is index.html
<!doctype html>
<html data-ng-app="gitHubApp">
<head>
<title>Github Repository App</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div data-ng-view></div>
<script src="vendor/angular.js"></script>
<script src="vendor/angular-route.js"></script>
<script src="app/app.js"></script>
<script src="app/controllers/gitHubApiController.js"></script>
<script src="app/services/gitHubApiServices.js"></script>
</body>
</html>
Please help me out with this problem. I had spend couple of hours but no luck.
Thank you for your effort
I have tried your code with
{{user.login}}
instead of {{$scope.user.login}} in plinkr and it works fine. It returns my username (or any other info I request from GitHub RestFull Api.
You should not use $scope in the view. Angular wil lfigure out the proper scope for you and inject it to be used by the view.
Have a look at this plunkr: http://plnkr.co/edit/16yyngPoZBgzVvfyWCDq
P.S: I have flattened your folder structure for the sake of simplicity.

Categories

Resources