Access form inside controller - angularjs

Here is my full code:
<html ng-app="myApp">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>
</head>
<body >
<div ng-controller="myController">
<form name="myForm">
<input ng-model="option" name="test">
{{myForm.$dirty}}
<button>Save</button>
</form>
</div>
<script>
angular.module('myApp',[]).controller('myController',function($scope){
$scope.option=2;
console.log($scope.myForm);
});
</script>
</body>
</html>
While {{myForm.$dirty}} works, console.log($scope.myForm) returns undefined!!! At the same time if I console.log($scope) I can see myForm as one of its properties!!!! As not to go mad, could someone explain this paradox?

I don't like this solution, but it works. Put a $timeout around the code that you would like to access the form. The $timeout kind of forces the code to wait until the form is fully rendered. (Don't forget to inject $timeout.)
angular.module('myApp',[]).controller('myController',function($scope, $timeout){
$scope.option=2;
$timeout(function() {
console.log($scope.myForm);
}); //Note that you don't need it to actually wait for any amount of time
The reason why you see the form if you console.log($scope) but not when you console.log($scope.myForm), is because the console will evaluate $scope when you expand it. By then, the form has rendered and attached to the scope.

Have you tried to put a watcher on the form ? I'm guessing that the form is simply not yet defined when the controller code is defined.
$scope.$watch('myForm', function(form) {
if(form) {
//check if form is defined
}
});

Related

Getting a variable from the ng-change function angularjs

I eventually need to create a select box with 4 options - Module 1 to 4. When an option is selected I need to send the number which was selected to the controller so that it can return different datasets for a chart.
That is the end goal, however experimenting with different code pens I simplified my problem down to just trying to get a variable from an input box.
I can get the value to appear on the template but I can not access it in the controller. How can I make the function in the controller work with the passed input data?
html
<body ng-app="plunker" ng-cloak>
<div ng-controller="MainCtrl">
<h1>Hello {{name}}</h1>
<p>Start editing and see your changes reflected here!</p>
</div>
<input placeholder="Module" type="text" ng-change="moduleChange(myModule)"
ng-model="myModule" ng-model-options="{debounce: 1000}">
{{myModule}}
</body>
script.js
angular.module('plunker', []).controller('MainCtrl',
function($scope) {
$scope.name = 'Plunker';
$scope.moduleChange = function(myModule) {
alert(myModule);
console.log(myModule);
$scope.name = myModule;
}
});
I thought that I would get an alert every time I changed the input but nothing is happening. nothing is logged to the console and the $scope.name variable appears to not change.
Where am I going wrong? Thx
Also any pointers for making it work inside a select box would be great too!
plunkr
Move ng-controller="MainCtrl" to the outer element (thats the reason why the function was not fired):
<body ng-app="plunker" ng-controller="MainCtrl" ng-cloak>
You don't need to pass the value into the function, you have the value with ng-model:
<input placeholder="Module" type="text" ng-change="moduleChange()" ng-model="myModule" ng-model-options="{debounce: 1000}">
$scope.moduleChange = function() {
alert($scope.myModule);
console.log($scope.myModule);
$scope.name = $scope.myModule;
}

Why are my angular curly braces not working?

My curly braces are showing up as curly braces, I don't get what's wrong, I did everything...when I use the controller to manipulate the input box, it works. But when I sumbit text into the input box on my browser, it doesn't do anything..
This is where I create my module:
'use strict';
var foodApp=angular.module('foodApp', []);
This is my html:
<script src="/lib/angular/angular.js"></script>
<!DOCTYPE html>
<html lang="en-us" >
<head>
<meta charset="utf-8">
<title>Food App</title>
</head>
<body>
<div ng-controller="foodController" ng-app="foodApp">
<input type="text" ng-model="foods"/>
<input type="submit" value="Healthy Lunch?" />
<br />
<br />
<h4>{{outcome}}</h4>
{{foods}}
</div>
<script src="/js/food.js"></script>
<script src="/js/controllers/foodController.js"></script>
</body>
</html>
This is my controller page:
foodApp.controller('foodController', function($scope)
{
var foods = $scope.foods;
$scope.outcome=foods;
var foodsArray=foods.split(',');
if(foodsArray.length<=4)
$scope.outcome="Bon Appetit!";
else if(foodsArray.length<=7)
$scope.outcome="Pig!";
else
$scope.outcome="One at a time, your scale is going to shout!!";
});
The problem is in fact in your controller. The code you have in your controller is only executed once, when the controller is constructed. As such the variable foods is undefined (since $scope.foods is also undefined). A couple of lines later, you try to run foods.split(..) but since it's undefined, it throws an exception and the application fails. This is shown as an error in the developer console of your browser.
To fix it you need to completely refactor your controller code.
foodApp.controller('foodController', function($scope)
{
$scope.handleFoodChange = function() {
$scope.outcome = $scope.foods;
if($scope.foods){
var foodsArray = $scope.foods.split(',');
if(foodsArray.length<=4)
$scope.outcome = "Bon Appetit!";
else if(foodsArray.length<=7)
$scope.outcome = "Pig!";
else
$scope.outcome = "One at a time, your scale is going to shout!!";
}
}
});
and in your view you should change your input to this:
<input type="text" ng-model="foods" ng-change="handleFoodChange()" />
That should make your application work as expected. Now, whenever you make a change in the input field, the function handleFoodChange is called, and it handles the logic that sets a value for the $scope.outcome variable.
Here's a Plunker showing it working

Angularjs controller nesting

I'm new to angular, I've tried some testing pattern and it's ok with the $scope variable but I can't make it work for a simple controller nesting. (and avoid using the $scope variable, instead I want to use "this")
Here is my sample HTML and javascript :
<!doctype html>
<html ng-app="appTest">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
</head>
<body>
<div ng-controller="FirstController as first">
<div>
First is {{first.text}}
</div>
<div ng-controller="SecondController as second">
Second is {{second.text}}
</div>
</div>
<script>
var app = angular.module("appTest",[]);
function printFirst() {
this.text = "first"
}
function printSecond() {
this.text = "second";
}
app.controller("FirstController",[printFirst]);
app.controller("SecondController",[printSecond]);
</script>
</body>
</html>
In the output html the angular variables inside curly brackets are not replaced and I don't know what's going on. I've tried to install Angular Batarang for debugging but the scope console is empty.
Obviously it's a silly mistake but I don't see where I'm wrong
Ok, the answer has nothing to do with my code, I was just using a too old version of Angularjs (1.0.8).
I moved to the last version 1.3.4 and it works fine.
Access the variable using $scope.text please instead of this.text.

AngularJS Basic Model Value Editing without Controller

I am looking at this basic example of AngularJS:
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.min.js"></script>
</head>
<body>
<div>
<label>Name:</label>
<input type="text" ng-model="yourName" placeholder="Enter a name here">
<hr>
<h1>Hello {{yourName}}!</h1>
</div>
</body>
</html>
It is the first example on the website and has no controller or anything. A textfield is attached to the model field yourName.
Now, I was wondering: since editing the text in the textfield changes the model value, how do I change the value of "yourName" programmatically? Thus far, I have found no simple way of doing this without adding a controller and whatnot.
Also, how can I attach a listener to that model to be notified whenever it changes?
In this case, you don't need a controller for this simple example. Angular behind the scenes is "creating"
$scope.yourName
In terms of changing it programmatically, you have to use a controller. In terms of watching for changes, use $scope.$watch
$scope.$watch($scope.yourName, function (newVal, oldVal) {
if (newVal !== oldVal) {
// logic here
}
});

Simple AngularJS running on JSFiddle

How do I make a jsfiddle out of the following code:
<html>
<head>
</head>
<body>
<div ng-app ng-controller="MainCtrl">
<ul>
<li ng-repeat="num in nums">
{{num}}
</li>
</ul>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script>
<script type="text/javascript" charset="utf-8">
function MainCtrl($scope) {
$scope.nums = ["1","2"];
}
</script>
</body>
</html>
My non working attempt: http://jsfiddle.net/zhon/3DHjg/ shows nothing and has errors.
You need to set some things up in jsFiddle for this to work.
First, on the left panel, under "Frameworks & Extensions", select "No wrap - in <body>".
Now, under "Fiddle Options", change "Body tag" to <body ng-app='myApp'>
In the JS panel, initiate your module:
var app = angular.module('myApp', []);
Check it out: http://jsfiddle.net/VSph2/1/
#pkozlowski.opensource has a nice blog post about how to use jsFiddle to write AngularJS sample programs.
You've defined your controller in a function scope that is not accessible to angular (angular is not yet loaded). In other words you are trying to call angular library's functions and helpers like below example before getting angular library loaded.
function onload(){
function MainCtrl(){}
}
To resolve this, switch your angular load type to be No wrap - in <body> like shown in screenshot.
here is a working example in jsfiddle
Click JAVASCRIPT button, choose angular version and place where u want include loaded script:
Then click HTML button and add ng-app in body tag. Its all:)
I am writing my answer for those who land on this page , I was used to use ng-module directive but in jsfiddle after half an hour I realized that ng-module is not allowed and you see no error , and when changed that ng-module to ng-app fiddle worked very well .I just wanted to share this .And no wrap (body) is required too.
<div ng-app="appX" ng-controller="appCtrl">
<p>{{greeting}}
</p>
</div>
var app=angular.module("appX",[]);
console.log(app);
app.controller("appCtrl",function($scope){
$scope.greeting="Hello World";
});
https://jsfiddle.net/cloudnine/trgrjwf1/7/
Since Angular 1.4.8 has been chosen by JSFiddle as the top option for Angular V1 in its JAVASCRIPT setting panel, more restriction applies: both ng-app and ng-controller should be declared in HTML to make it work.
Sample HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<input type="text" ng-model="sample" placeholder="type something here...">
<span>{{sample}}</span>
</div>
Sample JS:
angular.module('myApp', [])
.controller('myCtrl', function($scope) {});
https://jsfiddle.net/y170uj84/
Also tested with the latest Angular 1.6.4, by setting as External Resource.
For little experiments in angular 5, you can use https://stackblitz.com/.
This site is used in angular documentation to run live demo. For example, https://stackblitz.com/angular/eybymjopmav

Resources