AngularJS not working - can't pick up variables - javascript

I'm new to web designing and angular, and am copying something similar to this, where I consume a RESTful web service and use AngularJS to display the info in the JSON.
It doesn't seem to be working for me. My main.jsp file looks like:
<!doctype html>
<html ng-app>
<head>
<title>Your Bill</title>
<!-- Include the AngularJS library -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<!-- BillParser script -->
<script type="text/javascript" src="js/app.js"></script>
</head>
<body>
<div ng-controller="GetBill">
<p>The ID is {{bill.id}}</p>
<p>The content is {{bill.content}}</p>
</div>
</body>
</html>
And my app.js looks like:
function GetBill($scope, $http) {
$http.get('http://rest-service.guides.spring.io/greeting').
success(function(data) {
$scope.bill = data;
console.log('INITTED');
});
}
But it looks like the following on localhost/billparser/index:
The ID is {{bill.id}}
The content is {{bill.content}}
Is there something obvious I'm missing here? Excuse the 'bill' naming, it's going to eventually be something relating to bills, I just want to get Angular working first!
It looks like I'm getting the following error:
https://docs.angularjs.org/error/ng/areq?p0=GetBill&p1=not%20a%20function,%20got%20undefined
What do I need to do to fix this? I've never used js before so this is all new to me!
Thanks for your time.

It seems to me that you've missed something here: actually creating a Controller and registering it in your AngularJS application.
From The AngularJS documentation on Controllers (link here), that is what your app.js file should look like:
var myApp = angular.module('myApp',[]);
myApp.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
That is the featured example. In your case, more precisely, it would be:
var myApp = angular.module('myApp',[]);
myApp.controller('GetBill', ['$scope', '$http', function($scope, $http) {
$http.get('http://rest-service.guides.spring.io/greeting').success(function(data) {
$scope.bill = data;
// console.log('INITTED');
});
}]);
... and that should do it!

I sure hope that you had this inside the controller as:
app.controller('GetBill', ['$scope', '$http', function($scope , $http) {
$http.get('http://rest-service.guides.spring.io/greeting').
success(function(data) {
$scope.bill = data;
console.log($scope.bill);
});
}]);
Check the console for correct data. console.log($scope.bill);

After creating the controller as suggested by the other guys here, depending on your data, you will probably need an ng-repeat in your view.
If, for example, the data returned by getBill is an array of objects; after assigning the data to $scope.bill (which you did already) you would have to go into the view and change it to this:
<div ng-controller="GetBill">
<div ng-repeat="b in bill">
<p>The ID is {{b.id}}</p>
<p>The content is {{b.content}}</p>
</div>
</div>
But if you are not getting an array, you don't have to worry about it.

Related

Get data from controller to Component AngularJs

I have a problem. I create a component in AngularJs and I want to pass data from controller to Component.
Data comes to template component, but in the controller on component is undefined!
This is my code.
The controller
angular.module('testModule')
.controller('testController', ['$scope',
function($scope){
var vm = this;
vm.name = "John";
}
]);
The component. Here in the console.log(vm.name) its undefined! This is my problem.
angular.module('testModule')
.component('testComponent', {
bindings: {
"name": '='
},
controllerAs: 'ctrl',
controller: ['$scope', function ($scope) {
var vm = this;
console.log(vm);
console.log(vm.name);
}],
template: "<h2>Hi {{ctrl.name}}</h2>",
});
HTML
<html ng-app="testModule">
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.min.js"></script>
<script src="app.module.js"></script>
<script src="testController.js"></script>
<script src="testComponent.js"></script>
</head>
<body>
<div ng-controller="testController as ctrl">
<test-component name="ctrl.name"></test-component>
</div>
</body>
</html>
Here is the Plunker
Any idea? Thanks!
You should be hooking up over $onInit method to see what component bindings has.
vm.$onInit = function(){
console.log(vm.name);
}
The things which you were trying to do was totally doable till angular 1.5.X, but since AngularJS 1.6+ version they disabled prepopulating context of controller by introducing preAssignBindingsEnabled over $compileProvider. By default it is set to false. If you really want to see this working you could try to set the flag by below code(but I'd not recommend to use this). The main reason behind introducing this change is to make Angular and AngularJS API to look similar by design & architecture, eventually it will make one step closer to migration to Angular.
.config(function($compileProvider){
$compileProvider.preAssignBindingsEnabled(true);
})
Plunker

Create angular module after timeout is not working

I am trying to delay the module creation, but it doesn't work (I am using Chrome). Here is my code TRY THE JSFIDDLE
<!doctype html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.min.js"> </script>
</head>
<body>
<div ng-controller="MyCtrl">
Hello, {{name}}!
</div>
<script>
//initApp();
setTimeout(initApp, 1000);
function initApp() {
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl',
function($scope) {
$scope.name = 'Superhero';
});
}
</script>
</body>
</html>
If I remove the setTimeout and simply call initApp(), then it works. Can anyone explain why?
I am trying to embed an angular app into a page, and I am not allowed to add script tags to the HEAD. So I have to figure out some way to postpone the angular module initialization until after the angular.min.js is loaded and parsed.
It's not how you do it in angular way.
First i don't see any ng-app tag so your controler won't ever be called.
Second in order to delay the bootstrapping (and not using ng-app tag) you use angular.boostrap :
//initApp();
setTimeout(initApp, 1000);
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl',
function($scope) {
$scope.name = 'Superhero';
});
function initApp() {
angular.bootstrap('myApp');
}
For dynamic loading of javascript file see : lazy loading javascript the second point of the author of the post should do the job.
There is no need to use setTimeout. Browsers parse the JavaScript in the order they are declared in the HTML unless the async attribute is used.

AngularJS' ng:areq Bad Argument "{controller} is not a function", with textAngular on CodeIgniter

I'm trying to implement a text editor with textAngular in a CodeIgniter view, but it keep returning this error:
angular.js:13424 Error: [ng:areq] Argument 'wysiwygeditor' is not a function, got undefined
http://errors.angularjs.org/1.5.3/ng/areq?p0=wysiwygeditor&p1=not%20a%20function%2C%20got%20undefined
Where 'wysiwygeditor' is the name on ng-controller.
I've found tens of questions about that, and all seems to be caused by the same mistakes:
Unnamed ng-app directive
Omitted second argument on module definition
angular.module('myApp', [])
Version incompatibilities on controller declaration
None of those happens to be the problem, and I'm simply copying a code that already works. It's the demo.html from textAngular-1.5.0. I copy the code to a CodeIgniter view, include all the required libraries, but still get the error. Then I noticed it's happening whenever I declare a controller with Angular JS.
To make a better example:
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js'></script>
<div ng-app="myApp">
<div ng-controller="GreetingController">
{{greeting}}
</div>
</div>
<script>
var myApp = angular.module('myApp',[]);
myApp.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Bom dia!';
}]);
</script>
This code gives that error on CodeIgniter, but if I put it in a simple html file, works normally.
Here is your edited working code...
Dont use editor, Its waste of your time, They are mostly not working , some time its working...
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<body>
<div ng-app="myApp" >
<div ng-controller="GreetingController">
{{greeting}}
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('GreetingController', function($scope) {
$scope.greeting= "John";
});
</script>
</body>
</html>
My fault, my project was declaring an ng-app on a parent element, in a template file that I've forgot that existed. Removed this tag, and AngularJS stop returning that error.

How to write HTML inside elements with Angular

I'm beginning with Angular, and just wanted to make some tests with Ajax, retrieving a document into my page. It works perfectly, but then a new challenge appeared: I want to be able to add HTML inside a DOM element.
Normally, one would do that from a directive and the templates thingy. But I want to do it at runtime, using a controller.
This is my code:
$http.get("import.html").then(function(response){
var element = document.createElement("div");
element.innerHTML = response.data;
angular.element("#div1").innerHTML(element);
});
Maybe I'm not using correctly "angular.element"? I tried using document.getElementByID, but it doesn't work either. I receive correctly the information from the file, but I just don't find a way I can compile that HTML in runtime.
Any help with this?
edit for showing my full code:
HTML:
<!DOCTYPE html>
<html ng-app="miApp">
<head>
<meta charset="UTF-8">
<script src="angular.js"></script>
<script src="mainmodule.js"></script>
<link rel="stylesheet" href="bootstrap/css/bootstrap.css">
</head>
<body ng-controller="controlador1">
<div id="div1" ng-bind-html="myHtml" style="top:50px;left:50px">
</div>
</body>
</html>
JS:
(tested all your examples, none worked for me, this is the last I used)
app.controller('controlador1', ["$scope", "$http", "$sce", "$compile", function($scope, $http, $sce, $compile) {
$http.get("import.html").then(function(response) {
var parent = angular.element("#div1");
var element = angular.element($sce.trustAsHtml(response.data);
$compile(element)($scope);
parent.append(element);
});
}]);
Usually, you want to compile your HTML if it contains any angular functionality at all (you need to declare '$compile' in your controller dependency list):
myApp.controller('myController', ['$scope', '$sce', '$compile'],
$scope, $sce, $compile) {
$http.get("test.html")
.then(function(response){
var parent = angular.element("#div1");
parent.append($compile(response.data) ($scope));
});
}]);
if you are hell-bent on useing innerHTML, note that angular.element("#div1") is the same as $("#div1") in jQuery. So you need to write angular.element("#div1")[0].innerHTML= ...
Here's a plnkr: http://plnkr.co/edit/p3TXhBppxXLAMwRzJSWF?p=preview
In this, I have made use of $sce. It's a dependency injection of AngularJS, where it treats the HTML as safe to bind. You can read about it in AngularJS site. Please find below code and working jsfiddle for the raised concern:
HTML:
<div ng-app="app" ng-controller="test">
<div>
This is onload HTML
</div>
<div ng-bind-html="dynamicHtml"></div>
</div>
JS
var app = angular.module('app', []);
app.controller('test', function ($scope, $sce) {
$scope.dynamicHtml = $sce.trustAsHtml("<div>This is dynamic HTML!!");
});
[Update]
HTML:
<div ng-bind-html="dynamicHtml"></div>`
JS:
$http.get("import.html").then(function (response) {
$scope.dynamicHtml = $sce.trustAsHtml(response.data); //Assuming 'response.data' has the HTML string
});
You are not using correctly angular. If you use angular, you don't harly ever have to use DOM selector.
Scope is binded with ng-model and {{}} on the view.
Now your answer. To print html on the view, you can do it in that way:
In controller:
$http.get("import.html").then(function(response){
$scope.html = $sce.trustAsHtml(response.data);
});
In view:
<div ng-bind-html="html"></div>
And more easy way:
<ng-include="'url/import.html'"><ng-include>
That's it!!!

I am trying to understand AngularJS's controllerAs syntax

However after writing up a few examples to play around with the controllers would not load. I was getting an error:
firstController is not a function
After some googling I found that Angular 1.3.x no longer supports global controllers. All the examples I have seen of the new way of creating controllers seem to create them in my app.js file. I am confused, does this now mean that I must create all my controllers here rather than having a dedicated file for each controller. I have tried this to create the controller and still no luck:
UPDATE: I changed my controller to match jedanput's answer but changed $scope to this.
app.controller('firstController', [function(){
this.name = "Tim";
}]);
Also I find it very annoying that all that the majority of the example out there still reference the way it was done in Angular 1.2.
Any help would be greatly appreciated as I am having trouble understanding this issue.
EDIT: Here is my index.html file. Hopefully this will help you guys understand what is going wrong.
<!DOCTYPE html>
<html lang="en" xmlns:ng="http://angularjs.org" id="ng-app" ng-app="myApp">
<head >
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ControllerAs</title>
<meta name="description" content="">
</head>
<body>
<div class="content" ng-view=""></div>
<!-- jQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- AngularJS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular-route.js"></script>
<script type="text/javascript" src="../js/app.js"></script>
<!--Directives-->
<script type="text/javascript" src="../js/directives/it-works.js"> </script>
<!--Controllers-->
<script type="text/javascript" src="../js/controllers/firstController.js"></script>
<script type="text/javascript" src="../js/controllers/secondController.js"></script>
</body>
</html>
So far I have avoided Controllers as everything I have been doing could be done with directives and services but it is time I understood more about controllers. I think it may be something fundamental I am missing. Again any help is greatly appreciated.
UPDATE: still getting the same error. This is my app.js file. Maybe it can shed some light on the problem.
var app = angular.module('myApp',[
'ngRoute'
]);
app.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: "../partials/test-skeleton.html"
})
});
It should be
app.controller('firstController', ['$scope', function($scope){
$scope.name = "Tim";
}]);
Also, controllerAs syntax is synthetic sugar for the scope simply, you avoid using this:
<div ng-controller="oneCtrl">
{{name}}
</div>
And instead use this:
<div ng-controller="oneCtrl as one">
{{one.name}}
</div>
Which helps tremendously when you have nested controllers.
You're right, Angular allows for multiple different notations and that can be annoying and confusing. I would recommend you to stick with the guidelines from John Papas Angular Style Guide. He uses this:
(function() {
'use strict';
// Get reference to your application
angular.module('myapp')
// Add the controller
.controller('mycontroller',controller);
// This makes the injection of the controller arguments
// explicit
controller.$inject = ['$scope', '$http'];
// Here the actual controller is defined - where
// the arguments are injected on the same location as
// in the previous array
function controller($scope, $http) {
// Controller logic
});
})();
You want to keep stuff out of the global space. Really - you do. That's why he wraps everything in an Immediately-Invoked Function Expression (IIFE).
Also - you want to explicitly define what you're injecting ( the $inject array ). If not, you will not be able to minify later.
So I'm sorry - I just added another way of defining your AngularJS artefacts. From what I understand, this is one the more well known style guides out there. I've heard that he's working closely with the Angular guys to make sure his style guide will also make it easier to transition to the new Angular version.
And no - you do not need to put everything in 1 file - just make sure you have a file with angular.module('myapp',[]) loaded before any of the other files. This will declare the myapp module and will append the controller to it.
As I'm writing this - I realize that there's also another way: you create a new module in this file, append the controller and then load that module into your application. But yeah ... it's confusing.

Categories