I'm getting a curious error that seems to suggest my controller is not being created properly. Can anyone explain? This is my first SPA app so I'm programming in the dark a little bit.
Here is my master page:
<!DOCTYPE html>
<html ng-app="ibosApp">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>iBOS</title>
<script src="/Scripts/jquery-1.10.2.min.js"></script>
<script src="/Scripts/angular.min.js"></script>
<script src="/Scripts/angular-route.min.js"></script>
<script src="/Scripts/bootstrap-select.js"></script>
<script src="/angular/scripts/route-config.js"></script>
<script src="/Scripts/bootstrap-select.js"></script>
<link href="/Content/bootstrap.min.css" rel="stylesheet" />
<link href="/Content/bootstrap-select.css" rel="stylesheet" />
<link href="/Content/acs.css" rel="stylesheet"/>
<script type="text/javascript">
$(function () {
$('.selectpicker').selectpicker();
});
</script>
</head>
<body>
<div class="container body-content">
<ng-view/>
</div>
</body>
</html>
Here is my view template:
<div class="tab-content">
<div id="customers" class="tab-pane fade active in top-buffer" ng-controller="customerCtrl">
<form class="form-group">
<div class="container">
<div class="row">
<div class="col-sm-3">
<label for="customer-broker">Broker:</label>
<select class="selectpicker" id="customer-broker"></select>
</div>
<div class="col-sm-3">
<label for="customer-town">Town:</label>
<input type="text" class="form-control" id="customer-town"/>
</div>
<div class="col-sm-3">
<label for="customer-code">Code:</label>
<input type="text" class="form-control" id="customer-code"/>
</div>
<div class="col-sm-3">
<button ng-click="search()" class="btn">Search</button>
<button ng-click="myCustomers()" class="btn">My customers</button>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<label for="customer-company-name">Company name:</label>
<input type="text" class="form-control" id="customer-company-name"/>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<label for="customer-contact-name">Contact name:</label>
<input type="text" class="form-control" id="customer-contact-name"/>
</div>
</div>
<div class="row">
<div class="col-sm-3">
<label for="customer-customer-id">Customer ID:</label>
<input type="text" class="form-control" id="customer-customer-id"/>
</div>
</div>
</div>
</form>
</div>
</div>
<script type="text/javascript">
angular.module('ibosApp', ['angular-bootstrap-select', 'ngRoute'])
.controller("customerCtrl", function($scope, $http) {
$scope.loadBrokers = function() {
$http.get("/api/customers/getBrokers").success(function(data) {
$scope.brokers = data;
});
}
$scope.loadBrokers();
}
);
</script>
but I get the error "Argument 'customerCtrl' is not aNaNunction, got undefined" and the controller constructor is never called. Can anyone explain why?
M
EDIT - more code
Here is my route config...
angular.module("ibosApp", ["ngRoute"])
.config(function($routeProvider) {
$routeProvider.otherwise({
templateUrl: "/angular/components/booking-system/booking-system-template.html"
});
});
EDIT - full stack trace of error
Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.3.13/$injector/modulerr?p0=ibosApp&p1=Error%3…20d%20(http%3A%2F%2Flocalhost%3A4685%2FScripts%2Fangular.min.js%3A17%3A381)
There's a few things wrong.
You're setting ibosApp twice, i.e., angular.module("ibosApp", ["ngRoute"]) and angular.module("ibosApp", ['angular-bootstrap-select'])
You should only do this once, with all of your dependencies:
angular.module("ibosApp", ['ngRoute', 'angular-bootstrap-select']);
...and then use the getter syntax, which is the same, without the second parameter:
angular.module('ibosApp')
You can't define controllers in the view like you're doing unless you re-compile your angular app. It would be best to put your javascript into a separate file and include that script on your index page. The reason this isn't working is because your angular app compiles one time, then you load the view and define the controller, but angular doesn't know about that control since it wasn't there when you compiled it.
So:
app.js
angular.module("ibosApp", ["ngRoute", "angular-bootstrap-select"])
.config(function($routeProvider) {
$routeProvider.otherwise({
templateUrl: "/angular/components/booking-system/booking-system-template.html"
});
});
customerCtrl.js
angular.module('ibosApp').controller("customerCtrl", function($scope, $http) {
$scope.loadBrokers = function() {
$http.get("/api/customers/getBrokers").success(function(data) {
$scope.brokers = data;
});
}
$scope.loadBrokers();
}
);
And your markup would be
// previous script tags
<script src="app.js"></script>
<script src="customerCtrl.js"></script>
Is your module only defined in the template? If that's the case that might be your problem, the app isn't initialized since ng-app can't find the module you're trying to load. I would begin with separating JavaScript and HTML to make it easier on yourself.
Related
I've ben struggling with this for days, I can't see where is wrong. Thing is I've set up a angularjs web with routing and controllers but the controllers are showing the data empty in the views, but in the console I can see the $scope output with the corect data throught a console.log($scope). Here is the code
index.html
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://getbootstrap.com/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-md5/angular-md5.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js">
/script><sctipt src="http://getbootstrap.com/dist/js/bootstrap.min.js">
/sctipt><script src="js/main.js"></script>
</head>
<body ng-app='app'>
<div ng-view></div>
</body>
</html>
login.html
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="wrap">
<p class="form-title">
{{signin}}</p>
<form class="login">
<input type="text" ng-placeholder="{{user}}" required/>
<input type="password" ng-placeholder="{{password}}" required/>
<input type="submit" value="{{signin}}" class="btn btn-success btn-sm" />
<div class="remember-forgot">
<div class="row">
<div class="col-md-5">
<div class="checkbox">
<label>
<input type="checkbox" />
{{rememberme}}
</label>
</div>
</div>
<div class="col-md-7 forgot-pass-content">
{{forgotpassword}}}
</div>
</div>
</div>
</form>
</div>
</div>
</div>
main.js
var app=angular.module('app',['ngRoute']);
app.config(['$locationProvider','$routeProvider',function ($locationProvider,$routeProvider){
$routeProvider.
when('/login',{
templateUrl:'html/login.html',
controller:'loginController'
}).
when('/home',{
templateUrl:'html/home.html',
controller:'homeController'
}).
otherwise({
redirectTo:'/login'
});
}]);
app.run(function($rootScope){
$rootScope.urlapi='http://freecalendar.desirnet.com/api/api.php';
});
app.controller('loginController',function($scope,$rootScope,$location){
$scope={
'singin':'Iniciar sesión',
'user':'Usuario',
'password':'Contraseña',
'rememberme':'Recuérdame',
'forgotpassword':'Recordar contraseña'
};
console.log($scope);
$scope.login=function(){
var data=$.param({
'user':$scope.txtuser,
'password':$scope.txtpassword
});
$http.post($rootScope.urlapi,data)
.then(function(response){
response=response.data;
console.log(response);
if(response.error!=undefined){
$scope.errorlogin="El usuario y/o contraseña no son correctos";
} else {
$location.path('/home')
}
});
}
});
app.controller('homeController',function($scope,$rootScope,$location){
});
I really don't know what I'nm doing wrong, I follow many routing tutorials, but nothing.
In the console there are no errors only the $scope output.
typographical error in these line of code:
/sctipt>
You are assigning a new value to the $scope parameter in your loginController function
$scope={
'singin':'Iniciar sesión',
'user':'Usuario',
'password':'Contraseña',
'rememberme':'Recuérdame',
'forgotpassword':'Recordar contraseña'
};
You need to understand that after that you loose the link to the actual scope Angular is using. Angular simply has no way of knowing what are you intentions in your controller.
Here is the piece of code that will do the trick:
Object.assign($scope, {
'singin':'Iniciar sesión',
'user':'Usuario',
'password':'Contraseña',
'rememberme':'Recuérdame',
'forgotpassword':'Recordar contraseña'
});
Notice that it simply adds a few properties to the $scope object therefore Angular can perfectly reflect changes from your controller in your view.
In my application I'm making a get request through Angular's http service and in the view looping over the returned data to show an unordered list. But the problem is even though data is available after the get request , its not getting dispplyed on the page. Seems to be a CSS style problem, but don't know how to fix it. I want to show the unorder list within a bootstrap panel as a body.
Below is the angular piece of code inside the controlller for setting up the data
$http.get('/messages').success(function(data) {
console.log("Messages are "+data);
$scope.records=data;
});
Here is the html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>jQuery Bootstrap News plugin</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="/libs/css/bootstrap.min.css"/>
<link rel="stylesheet" href="/libs/css/font-awesome.min.css"/>
<link rel="stylesheet" href="/libs/css/custom.css"/>
<script src="/libs/js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script src="/libs/js/newsbox.min.js" type="text/javascript"></script>
<script src="/libs/js/angular.min.js" type="text/javascript"></script>
<script src="/libs/js/main.js" type="text/javascript"></script>
</head>
<body ng-app="mean" ng-controller="MainCtrl">
<br/>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<span class="glyphicon glyphicon-list-alt"></span><b> What you wanna do before you die ...</b>
</div>
<div ng-cloak class="panel-body">
<div class="row">
<div class="col-xs-12">
<ul class="demo1">
<li class="news-item" ng-repeat="item in records">
<table cellpadding="4">
<tr>
<td >
<img class="img-circle" width="60"
ng-src="/images/{{($index+11) % 10}}.png"/>
</td>
<td ng-cloak>
{{$index+1}}. {{item.username}}
</td>
</tr>
</table>
</li>
</ul>
</div>
</div>
</div>
<div class="panel-footer"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-1 ">
<form name="messageForm" novalidate="novalidate" ng-submit="onSubmit()" id="message-box">
<div class="form-group">
<textarea required ng-model="formModel.message"
style="background-color:#ffffe6;border:double 4px orange;border-radius: 0.5em;" rows="3" cols="50" id="message" placeholder="Write your message and press enter.."> </textarea>
<button class="btn btn-primary" type="submit">Shoot it</button>
</div>
<p ng-cloak class="help-block" ng-show="formModel.nameError">Looks like you forgot to mention your name !!!</p>
<p ng-cloak class="help-block" ng-show="formModel.messageEmpty">Really you don't wanna do anything before you die !!! </p>
<p ng-cloak class="help-block" ng-show="formModel.messageTooLong">You are trying to do too many things buddy, just 150 characters !!! </p>
</form>
</div>
</div>
</div>
<script type="text/javascript">
$(function () {
$(".demo1").bootstrapNews({
newsPerPage: 12,
autoplay: true,
pauseOnHover:true,
direction: 'up',
newsTickerInterval: 4000,
onToDo: function () {
//console.log(this);
}
});
});
</script>
</body>
</html>
When I check through chrome dev tool, data is present in that unordered list, data is present but somehow not getting displayed properly within bootstrap panel.
See this image
I noticed there is one undefined element at the bottom of unordered list while checking through dev tools. Any idea whats going wrong?
The panel body is empty
Why is the [ul] tag style set to "height:0px; overflow-y:hidden"? -- this would hide your content
you could also move the ng-cloak to the div.panel-body to the div.row and remove it from the child td
--
Delay bootstrapNews binding
$(function(){
if ($('.panel-body[ng-cloak]').length > 0)
return window.setTimeout(arguments.callee, 10);
$(".demo1").bootstrapNews({...});
});
I think you should write a directive for getting a callback when ng-repeat is done and that is a better solution instead of any 'delay' tactics.
Might help you to go through how I have done in my code- used a directive to emit a render finished event:
dashboard.directive('onFinishRender', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit(attr.onFinishRender);
});
}
}
}
});
In the controller I keep the event listener:
$scope.$on('dataLoaded', function(ngRepeatFinishedEvent) {
// your code to add bootstrapNews binding
});
and in the html side, I call them like this:
<div class="add_tenant_name" ng-repeat="tenant in tenants" on-finish-render="dataLoaded">
// more divs
</div>
I have the requirement, that all error messages have to be shown in the header of the application. How can I do that with angular?
If I have this application (see on plunker):
<body>
<div id="header">
<!-- I want error messages to show up here -->
</div>
<form name="myForm">
<label>Email</label>
<input name="myEmail" type="email" ng-model="user.email" required="" />
<div ng-messages="myForm.myEmail.$error">
<div ng-message="required">required</div>
<div ng-message="email">invalid email</div>
</div>
</form>
<p>Your email address is: {{user.email}}</p>
</body>
What I need is to have the error messages in the header div. How can I do that?
Fixed demo here.
Just access the error the way same as in form, as when you set <form name="myForm" >, then you will get $scope.myForm = [yourFormObject], then access free anywhere in same controller.
Angular Form Document
Under the title Binding to form and control state
A form is an instance of FormController. The form instance can optionally be published into the scope using the name attribute.
And, even access the $error in controller by $scope.$watch('formName.fieldName.$error',function(nv,ov){});
// Code goes here
var app = angular.module('plunker', ['ngMessages']);
app.controller('appCtrl', function($scope) {
$scope.$watch('myForm.myEmail.$error', function(nv, ov) {
console.info(nv);
}, true);
});
/* Styles go here */
hr {
margin: 20px 0;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
</script>
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular-messages.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="appCtrl">
<div id="header">
<div ng-show="myForm.myEmail.$error.required">required</div>
<div ng-show="myForm.myEmail.$error.email">invalid email</div>
</div>
<hr />
<form name="myForm">
<label>Email</label>
<input name="myEmail" type="email" ng-model="user.email" required="" />
<div ng-messages="myForm.myEmail.$error">
<div ng-message="required">required</div>
<div ng-message="email">invalid email</div>
</div>
</form>
<p>Your email address is: {{user.email}}</p>
</body>
</html>
You'll have two distinct controller.In header controller, you'll be displaying your error messages.
Then your controller will be communicating over either $rootScope or service
I am very new to AngularJS. I have made an html component which is to be reused across the whole app. Let's say this component gives out the basic info of a product. The basic structure of the HTML is as below:
<div class="visible-sm-block">
<div class="row">
<div class="col-sm-2">
<img class="img-circle img-responsive" alt="Image of product"
ng-src="{{}}"/>
</div>
<div class="col-sm-10">
<label>{{ProductName}}</label>
<p>{{CompanyName}}</p>
<p>{{ShippedTo}}</p>
</div>
</div>
</div>
The product.js file goes as:
(function() {
'use strict';
angular
.module('product')
.directive('productDetails', productDetails);
/** #ngInject */
function productDetails() {
var directive = {
restrict: 'E',
templateUrl: 'app/components/productDetails/productDetails.html'
};
return directive;
}
})();
The small HTML component would be reused across other HTML pages in the app like this:
<product-details></product-details>
Now the problem is I cannot bind data with the HTML component when it is used across my pages. The controller for those pages is in a separate folder: app/productshipping/productshipping.controller.js
I tried using ng-controller="controller_name" in the HTML component itself but no result came. :( Please help.
This is really an interesting question. The code is given below. I am developing an angular framework. So do let me know if you need any further assistance.
Product.js file as follows
"use strict";
angular.module("app",[]);
angular.module("app").controller("productController", ['$scope', function ($scope) {
}]);
angular.module("app").directive("tmHtml", function () {
return {
transclude: false,
scope: {
productName: '#',
companyName: '#',
shippedTo: '#'
},
controller: "productController",
templateUrl: "/templates/HideShow.html"
};
});
Template HTML file as follows
<html ng-app="app">
<head>
<title></title>
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
<script src="../Scripts/jquery-1.10.2.js"></script>
<script src="../Scripts/bootstrap.js"></script>
</head>
<body ng-controller="productController">
<div class="visible-sm-block">
<div class="row">
<div class="col-sm-2">
<img class="img-circle img-responsive" alt="Image of product" ng-src="{{}}" />
</div>
<div class="col-sm-10">
<label>{{productName}}</label>
<p>{{companyName}}</p>
<p>{{shippedTo}}</p>
</div>
</div>
</div>
</body>
</html>
How to reuse this as follows
<html ng-app="app">
<head>
<title></title>
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
<script src="../Scripts/jquery-1.10.2.js"></script>
<script src="../Scripts/bootstrap.js"></script>
<script src="../Scripts/angular.js"></script>
<script src="../js/Product.js"></script>
</head>
<body>
<div>
<tm-Html product-Name="Sankar" company-Name="Sankar" shipped-To="Sankar">
</tm-Html>
</div>
</body>
</html>
after watching this presentation (https://www.youtube.com/watch?v=ImR0zo1tA_I) I wanted to try Angular JS. I copied the code, exactly what was on the screen, but i doesn't work. I tried it in my browser, in my page (http://thecodemaker.com.pl), I was doing research about AngularJS but it still doesn`t want to work.
Code :
<!DOCTYPE html>
<html ng-app="basicApp">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/bootstrap.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
</head>
<body ng-controller="TodoController">
<form>
<div class="container">
<div class="panel panel-primary">
<div class="panel-heading">
<h1 class="panel-title"><b>ToDo List</b></h1>
</div>
<ul class="list-group">
<li class="list-group-item" ng-repeat = "todo in todos">
<div class="checkbox">
<label>
<input type="checkbox"> {{todo}}
</label>
<button type="button" class="close">×</button>
</div>
</li>
</ul>
</div>
<div class="form-group has-feedback">
<label class="control-label invisible">Enter Task</label>
<input type="text" class="form-control text-primary"></input>
<button type="button" class="close form-control-feedback text-muted">±</button>
</div>
<div class="alert alert-info">Enter new task to get started</div>
<div class="alert alert-danger">Maximum number of tasks allowed : 5</div>
</div>
</form>
<script src="js/bootstrap.min.js"></script>
<script src="js/jquery-1.11.2.js"></script>
<script>
angular.module("basicApp", [])
.controller("TodoController", ["$scope", function($scope) {
$scope.todos =['Buil an atomic bomb','Sell it on ebay']
}
</script>
</body>
</html>
Any ideas what is wrong ?
There seems to be a lot wrong with your snippet. For one, your submit/add button is not bound to an event listener or anything so it's not doing anything that you'd want (like adding an item to the property on your controller's $scope).
Check out the Todo example on Angular's official website, it's more up to date.
https://angularjs.org/ (scroll down).
Here's the video for it: https://www.youtube.com/watch?v=WuiHuZq_cg4
There is an error : Bootstrap's JavaScript requires jQuery, which means you need to add jQuery library to your project, required by bootstrap.js
Starting with Angular 1.3.x, you can no longer declare a controller as a generic global function on window. Controllers must now use the more current form of component declaration.
<script>
angular.module("basicApp", [])
.controller("TodoController", ["$scope", function($scope) {
$scope.todos =['Buil an atomic bomb','Sell it on ebay']
}
</script>
In the HTML, change ng-app="" to ng-app="basicApp.