I'm new to AngularJS and I'm trying to bind some data I fetch with an Http call when user clicks a button. Data binding works fine when I use it outside of test() but it does not inside test() which gets called on a button click.
What am I doing wrong?
<head>
<script>
function test() {
fetch(url)
.then(function(response) {
return response.json();
})
.then(function(myJson) {
var response = myJson;
var results = parseJSON(response);
angular.module("blabla", [])
.controller("myController", function($scope) {
$scope.test= {};
$scope.test.title = "testttt!";
});
});
}
</script>
</head>
<body ng-app="blabla">
<div class="search">
<form id="search_form" method="get" onSubmit="return test()">
<input type="text" class="_search" placeholder="Search" id="search_">
<input title="Search" value="" type="submit" class="search_btn">
</form>
</div>
<div ng-controller="myController">
<h2>Welcome {{test.title}}</h2>
</div>
</body>
Replace onSubmit="return test()" by onSubmit="test()"
The Angular interpreter is trying to invoke the statement (I believe that it thinks it is a function) return (with parameters test()
Also, test() needs to be declared in the $scope of your controller myController.
It might be a good idea to get a skeleton demo Angular app and try to understand how it works by making small modifications.
Related
I have the following Angular code
controller:
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.job = null;
vm.create = function (job) {
vm.job = job;
}
});
HTML:
<div ng-controller="MainCtrl as vm">
<span data-ng-bind="vm.job.position"></span>
<form name="form" data-ng-submit="vm.create(vm.job)">
<label for="position">Position</label>
<input id="position" name="vm.job.position" type="text" data-ng-model="vm.job.position" />
<button>Create</button>
</form>
</div>
But when I submit the form I don't see the Position value.
Any idea why?
Because
You forgot to add ng-app to the body or html element
You're using angular 1.0.8, which is completely obsolete, and doesn't support controller as.
Note that you don't even need to submit, since the job you're binding is already vm.job. Your create(vm.job) method call does nothing: it assigns vm.job to vm.job.
I have a method in my Web API controller returning a boolean:
[HttpGet]
public bool ValidateEmployee(string id)
{
return myRepository.VerifyEmployeeId(id);
}
and here is my UI that is calling that Web API via Angular;
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Employee ID/PIN</title>
<script src="../../Scripts/angular.js"></script>
<script src="EmployeeLoginCtrl.js"></script>
</head>
<body ng-app="myClassesApp">
<div ng-controller="myClassesController">
<form ng-submit="ValidateEmployeeId()" method="get" id="frmLogin" action="">
<input ng-model="empId" type="text" id="txtEmpId" />
<br />
<input type="submit" value="Submit" id="btnSubmit" />
<br />
<span id="lblMsg">{{EmployeeValidate}}</span>
</form>
</div>
</body>
</html>
and here is my angular controller:
(function () {
angular.module("myClassesApp", []).controller("myClassesController", EmpCtrlFunction);
EmpCtrlFunction.$inject("$scope", "$http");
function EmpCtrlFunction($scope, $http) {
$scope.ValidateEmployeeId = function () {
alert($scope.empId);
$http.get('http://localhost:49358/api/myClasses/ValidateEmployee/' + $scope.empId).
then(function (result) {
alert(result);
$scope.EmployeeValidate = result.data;
});
}
};
})();
When I enter an id and click a button, the line alert($scope.empId); gets executed and then it never gets to $http.get
What am I doing wrong?
dont use alert since alert is blocking and causes all kinds of problems in angular, use console.log instead to dump variable values and use the console tab in your browser to view output
console.log($scope.empId);
use the NET tab in your browser to view what HTTP requests are being made
The way you inject dependencies is wrong. it should be
EmpCtrlFunction.$inject = ["$scope", "$http"];
as $inject is not a function.
I am bringing in some simple data via a service that uses angular-resource like so:
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function (InvoiceService) {
var vm = this;
InvoiceService.query(function (data) {
vm.invoices = data;
});
vm.submit = function (form) {
console.log(form)
};
});
And the html:
<form name="invoices" role="form" novalidate>
<ul>
<li ng-repeat="invoice in vm.invoices">
<input type="checkbox" id="{{'id-' + $index}}" />
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="vm.submit(invoices)" />
</ul>
</form>
Everything works fine; the data is displays in the view as expected.
The question:
What I'd like to do is be able to select a checkbox, grab the bit of data associated with that checkbox, and pass it along to the next controller/view on submit. How can I do this?
So, what do I do next? Am I on the right track?
**EDIT: added all angular code to help clarify
Posting answer as reply too big to be useful.
You should be using $scope to isolate the controller's data from the rest of the page.
Read up about ng-model http://docs.angularjs.org/api/ng/directive/ngModel and how to use it to two-way-bind checkbox value to a controller variable. No need to use theFormName if you call $scope.submit = function() { } as your ng-model variable will be available in $scope already.
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function ($scope, InvoiceService) {
InvoiceService.query(function (data) {
$scope.invoices = data;
});
$scope.submit = function () {
// FIXME to access a property of each $scope.invoices
console.log('checkbox1=' + $scope.invoices[0].checkbox1);
};
});
Then the HTML:
<form role="form" novalidate ng-controller="DashboardListCtrl"><!-- EDIT: added ng-controller=, remove name= -->
<ul>
<li ng-repeat="invoice in invoices"><!-- EDIT: remove 'vm.' -->
<input type="checkbox" id="{{'id-' + $index}}" ng-model="invoice.checkbox1" /><!-- EDIT: added ng-model= -->
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="submit()" /><!-- EDIT: remove 'vm.' -->
</ul>
</form>
I've been following a course to learn angularjs and I can't seem to get a simple ng-click binding to work.
HTML:
<body ng-controller="MainController">
<div ng-app="githubViewer">
<h1>{{message}}</h1>
<div>{{ error }}</div>
{{username}}
<form name="searchUser">
<input type="search" placeholder="Username to find" ng-model="username" />
<input type="submit" value="Search" ng-click="search(username)" />
</form>
<div>
<div>{{user.name}}</div>
<img ng-src="http://www.gravatar.com/avatar/{{user.gravatar_id}}" title="{{user.name}}">
{{user.gravatar_id}}
</div>
</div>
</body>
Javascript:
(function () {
var module = angular.module("githubViewer", []);
var MainController = function ($scope, $http) {
var onUserComplete = function (response) {
$scope.user = response.data;
};
var onError = function (reason) {
$scope.error = "Could not fetch the user";
$scope.reason = reason;
};
$scope.username = "angular";
$scope.message = "Github Viewer";
$scope.search = function (username) {
$http.get("https://api.github.com/users/" + username)
.then(onUserComplete, onError);
};
};
module.controller("MainController", MainController);
}());
When you click the search button (search for username "odetocode" or "robconery") it is supposed to display an image but the click event does not seem to be firing. I have searched the documentation and looked over the course again but I can't see what I'm doing wrong.
I'm currently using version 1.2.16 of angularjs.
You have the ng-controller declaration outside of the ng-app declaration right now:
<body ng-controller="MainController">
<div ng-app="githubViewer">
It should be the other way around, or have both on the same element
<body ng-app="githubViewer" ng-controller="MainController">
<div>
AngularJS evaluates your code, and checks for any directives you have declared from the ng-app element down, including the element it is declared on; This currently is missing the ng-controller directive, as it is placed on a parent element of the ng-app element.
You need to put the controller within the context of the module to have it within its scope.
Like so
<body ng-app="githubViewer" ng-controller="MainController">
Demo here
Here is the jsfiddle.
http://jsfiddle.net/CLcfC/
code
var app = angular.module('app',['']);
app.controller('TestCtrl',function($scope){
$scope.text = 'Change Me';
$scope.$watch('text',function(){
alert('Changed !');
});
})
HTML
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="TestCtrl">
<input type="text" ng-model='text'/>
<span>{{text}}</span>
</div>
</div>
I am not able to see the change in $scope.text. Please help.
This is so easy but what am I missing?
Change the module creation to this, make sure you don't put a empty string in the []. (Obvious the empty string is not a module that can be injected.)
var app = angular.module('app', []);
Demo: http://jsfiddle.net/MWa66/
Your JavaScript file loads after the AngularJS initialization and that's why it fails to find your module. In order to fix it change the initialization to a manual initialization.
First change your HTML and remove the ng-app directive:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<div id="appRoot">
<div ng-controller="TestCtrl">
<input type="text" ng-model='text'/>
<span>{{text}}</span>
</div>
</div>
Then go to your JavaScript and use angular.bootstrap method to manually attach your module:
var app = angular.module('app',[]);
app.controller('TestCtrl',function($scope){
$scope.text = 'Change Me';
$scope.$watch('text',function(){
alert('Changed !');
});
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById('appRoot'), ['app']);
});
You can find more help on manual AngularJS initialization here.
Thank you! I solved this annoying thing!
The solution that worked for me was that I use angular UI router and there I had used the following code
.state('app.monimes', {
url: "/monimes",
views: {
'menuContent' :{
templateUrl: "templates/monimes.html",
controller: 'sampleCtrl'
}
}
})
so then in the controller I had
/***
*
*Controller for tests..
*/
.controller('sampleCtrl',['$scope','sampleService', function($scope, $sampleService) {
$scope.username="em";
// Watch for changes on the username property.
// If there is a change, run the function
$scope.$watch('username', function(newUsername) {
// uses the $http service to call the GitHub API
// //log it
$scope.log(newUsername);
// and returns the resulting promise
$sampleService.events(newUsername)
.success(function(data, status, headers) {
// the success function wraps the response in data
// so we need to call data.data to fetch the raw data
$scope.events = data.data;
});
},true);
}
]);
and in the view I had
<div>
<label for="username">Type in a GitHub username</label>
<input type="text" ng-model="username" placeholder="Enter a GitHub username, like a user" />
<pre ng-show="username">{{ events }}</pre>
</div>
but that didn't work.
so I added ng-controller="sampleCtrl"
to the div and now it works :D
so that means that the view is loaded after the controller loads and the watcher doesn't get added to the watching variable.