I'm teaching myself AngularJS by trying to make a simple app. I'm having some trouble with data binding when using a controller.
todo-item.js
'use strict';
angular.module('todoItem', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/todoItem', {
templateUrl: 'todo-item/todo-item.template.html',
controller: 'TodoItemCtrl'
});
}])
.controller('TodoItemCtrl', [function() {
this.test = [1, 2, 3, 4];
}]);
todo-item.template.html
<p>This is the partial for todo item.</p>
<p>
this is just a test
</p>
<p>{{$ctrl.test}}</p>
<ul>
<li ng-repeat="i in $ctrl.test">{{i}}</li>
</ul>
What I am seeing is the web-page display:
This is the partial for todo item.
this is just a test
So this indicates the template is rendering, however without the data binding dependent part...
If I put a console.log(this.test) in the controller code just after the line this.test = [1, 2, 3, 4], it does print the array object to the console Array(4) [ 1, 2, 3, 4 ]. So I know the controller code must be running...
What am I missing?
Also being new to AngularJS, I'm not familiar with debugging in this framework yet. How would you normally debug something like this? Can I goto the console and do something like >>$ctrl?
In case it helps here is app.js
'use strict';
// Declare app level module which depends on views, and core components
angular.module('todoApp', [
'ngRoute',
'todoList',
'todoItem'
]).
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.otherwise({redirectTo: '/todoList'});
}]);
and index.html:
<!DOCTYPE html>
<html lang="en" ng-app="todoApp">
<head>
<meta charset="utf-8">
<title>ToDo AngularJS App</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="app.css">
</head>
<body>
<div ng-view></div>
<script src="lib/angular/angular.js"></script>
<script src="lib/angular-route/angular-route.js"></script>
<script src="app.js"></script>
<script src="todo-list/todo-list.js"></script>
<script src="todo-item/todo-item.js"></script>
</body>
</html>
I think you might need to provide controllerAs: '$ctrl' in your route provider, so
$routeProvider.when('/todoItem', {
templateUrl: 'todo-item/todo-item.template.html',
controller: 'TodoItemCtrl',
controllerAs: '$ctrl'
});
To answer the question while avoiding $scope and instead using something more isolated as the AngularJS docs suggest, components is the way to go.
To achieve this I changed app.js to handle the routes and crucially use components:
'use strict';
// Declare app level module which depends on views, and core components
angular.module('todoApp', [
'ngRoute',
'todoList',
'todoItem'
])
.config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.
when('/todoList', {
template: '<todo-list></todo-list>'
})
.when('/todoItem', {
template: '<todo-item></todo-item>'
})
.otherwise({redirectTo: '/todoList'});
}]);
Then I implemented the component in todo-item.js:
'use strict';
angular.module('todoItem', ['ngRoute'])
.component('todoItem', {
templateUrl: 'todo-item/todo-item.template.html',
controller: 'TodoItemCtrl'
})
.controller('TodoItemCtrl', [function() {
this.test = [1, 2, 3, 4];
}]);
To use $scope see Anurag Srivastava answer. I'm not sure what's the best way, as I have much to learn.
Related
I'm working on a Angular route example but for some reason it's not working.
I've tried many pages and many things but doesn't seem to help.
Here's an
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="../Scripts/angular.min.js"></script>
<script src="../Scripts/angular-route.min.js"></script>
<script>
var app = angular.module("Main", ["ngRoute"]);
app.config(["$routeProvider", function ($routeProvider) {
$routeProvider.
when("/first", {
templateUrl: "_Pages/test.html",
controller: "first"
}).
when("/second", {
templateUrl: "_Pages/index.html",
controller: "second"
});
}]);
app.controller("first", function ($scope) {
$scope.list = [1, 2, 3, 4, 5];
});
app.controller("second", function ($scope) {
$scope.list = [1, 2, 3];
});
</script>
</head>
<body ng-app="Main">
<ul>
<li> first partial </li>
<li> second partial </li>
</ul>
<div ng-view></div>
</body>
</html>
Any advice would be pleasant!
it seems to be working fine. And Please check the angular version is compatible with the route. i create a sample Plunker
<script data-require="angular.js#1.5.10" data-semver="1.5.10" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.min.js"></script>
<script data-require="angular-router#1.2.0-rc1" data-semver="1.2.0-rc1" src="https://code.angularjs.org/1.2.0rc1/angular-route.js"></script>
It's likely that there is a version issue in your angular js file inclusion.
Either you replace your file inclusion code by,
<script src="http://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://code.angularjs.org/1.2.16/angular-route.min.js"></script>
(or)
Copy the entire code from here. Here's the working version of angular JS & Route.
DEMO
Note : I changed templateUrl to template for demo purpose.
If you're using Angular 1.6, it's probably to do with the changes made to the default hash prefix. That is that as from v1.6.0 upwards ! is the default hash prefix, whereas it used to be "" (empty string).
To fix this issue, either...
Change your links as follows:
<li> first partial </li>
<li> second partial </li>
Or
Remove the hash prefix by injecting $locationProvider into the app.config and setting the hash prefix to the empty string as follows:
app.config(["$routeProvider", "$locationProvider", function ($routeProvider, $locationProvider) {
// with this the links can remain: href="#/first" and href="#/second"
$locationProvider.hashPrefix("");
$routeProvider.
when("/first", {
templateUrl: "_Pages/test.html",
controller: "first"
}).
when("/second", {
templateUrl: "_Pages/index.html",
controller: "second"
});
}]);
Further Reading:
Angular Issues - Angular 1.6.0 incorrectly redirects to hashbang
Angular Docs - Migrating from v1.5 to 1.6
I am building a website using angularJS and PHP. Website has many pages like- Home, About Us etc.
So, I have created a common header for the website which I included in my HTML view like this:
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="angular.min.js"></script>
<script src="angular-route.min.js"></script>
<script src="commonController.js"></script>
<script src="homeController.js"></script>
<script src="loginController.js"></script>
<script src="app.js"></script>
</head>
<body>
<div class="header" ng-controller="CommonController"
ng-include="'header.html'"></div>
<div class="main" ng-view></div>
</body>
</html>
and the header (header.html) page looks like this:
<nav class="navbar-inverse navbar-fixed-top" role="navigation">
Home
<a href="#/notifications" >{{vm.commonId}}</a>
</nav>
and header controller has a http call which fetches user id and I am trying to show this id as a label for one of the links mentioned above (commonController.js)
(function() {
angular
.module('myApp.common', ['ngRoute'])
.factory('myCommonService', function($http) {
var baseUrl = 'api/';
return {
getBasicUserInfo:function() {
return $http.get(baseUrl + 'getBasicUserInformation');
}
};
})
.controller('CommonController', function($scope, $routeParams, myCommonService) {
var vm = this;
myCommonService.getBasicUserInfo().success(function(data) {
vm.commonId = data.id;
});
});
})();
But when I navigate through pages, header remains same. So, I'm not able to initiate that http call. There are many pages in my website.
Can this be done? I'm pretty much new to this platform.
Route (app.js)
(function() {
angular.module('myApp', [
'ngRoute',
'myApp.login',
'myApp.home',
'myApp.common'
])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/login', {
controller: 'LoginController',
templateUrl: 'loginView.html',
controllerAs: 'vm'
})
.when('/home', {
controller: 'HomeController',
templateUrl: 'homeView.html',
controllerAs: 'vm'
})
.otherwise({
redirectTo: '/login'
});
}]);
})();
P.S: I excluded other pages to reduce complexity and make my query easy to understand.
Thanks!
Seems to me all that is missing is letting the template know the scoped alias for the controller
<div class="header" ng-controller="CommonController as common"
ng-include="'header.html'"></div>
and in header.html
{{common.commonId}}
Note that I've used common instead of vm as some of your routes are using vm and it's best to avoid conflicts.
If you want to trigger an update on page navigation (ie, route change), change your CommonController to this
.controller('CommonController', function($scope, myCommonService) {
var ctrl = this;
var update = function() {
myCommonService.getBasicUserInfo().then(function(res) {
ctrl.commonId = res.data.id;
});
};
update();
$scope.$on('$routeChangeSuccess', update);
});
You should be able to do this:
.when('/login', {
controller: 'LoginController',
templateUrl: 'loginView.html',
resolve: function(){ //your code here }
controllerAs: 'vm'
})
instead of getting it from the controller
I think that your issue might be that the include can't read the controller, so instead try this:
<nav class="navbar-inverse navbar-fixed-top" role="navigation" ng-controller="CommonController as vm">
Home
<a href="#/notifications" >{{vm.commonId}}</a>
</nav>
Note that you're also missing the controllerAs syntax so I added that.
And remove ng-controller from here:
<div class="header" ng-include="'header.html'"></div>
I'm not sure how can I implement proper Angular routing in web api application. I'm able to open the pages using this approach: http://localhost:52876/HTML/app/borrower.html
The Angular controller loads fine and all functionality is there from the angular side.
Now, I want to be able to open the views in a bit better view, using ng-route, so for example http://localhost:52876/HTML/app/borrower.html will become http://localhost:52876/borrower.
I included the ng-route.js file in the html files which I'm using in my angular app.
Also in app.js I have this:
'use strict';
var modules = [
'app.controllers',
'LoanAdminApplicationController',
'ngCookies',
'ngResource',
'ngSanitize',
'ngRoute',
'ui.router',
'LocalStorageModule',
'angular-loading-bar'
];
var app = angular.module('app', modules);
app.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider.when("/home", {
controller: "homeController",
templateUrl: "/app/views/home.html"
});
$routeProvider.when("/login", {
controller: "loginController",
templateUrl: "/HTML/login.html"
});
$routeProvider.when("/signup", {
controller: "signupController",
templateUrl: "/app/views/signup.html"
});
$routeProvider.when("/register", {
controller: "signupController",
templateUrl: "/app/views/register.html"
});
$routeProvider.when("/refresh", {
controller: "refreshController",
templateUrl: "/app/views/refresh.html"
});
$routeProvider.when("/tokens", {
controller: "tokensManagerController",
templateUrl: "/app/views/tokens.html"
});
$routeProvider.when("/borrower", {
controller: "borrowerController",
templateUrl: "/HTML/app/borrower.html"
});
$routeProvider.otherwise({ redirectTo: "/home" });
});
The html markup (I removed the content):
<!DOCTYPE html>
<html ng-app="app">
<head>
</head>
<body ng-controller="BorrowerQuickQuoteApplication">
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="/assets/js/jquery.min.js"></script>
<script src="/assets/js/modernizr.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="/assets/js/bootstrap.min.js"></script>
<script src="/Scripts/angular.js"></script>
<script src="/Scripts/angular-cookies.min.js"></script>
<script src="/Scripts/angular-resource.min.js"></script>
<script src="/Scripts/angular-sanitize.min.js"></script>
<script src="/Scripts/angular-route.min.js"></script>
<script src="/Scripts/angular-ui-router.min.js"></script>
<script src="/Angular/controllers.js"></script>
<script src="/Angular/LoanApplicationController.js"></script>
<script src="/Angular/services.js"></script>
<script src="/Scripts/angular-local-storage.min.js"></script>
<script src="/Scripts/loading-bar.min.js"></script>
<script src="/Angular/app.js"></script>
</body>
</html>
Any idea what I need to do in order to make this working?
Should I modify the RouteConfig.cs file or I need to do anything else as well?
You don't navigate with the file name as you are doing that's angular route job to do for example
$routeProvider.when("/borrower", {
controller: "borrowerController",
templateUrl: "/HTML/app/borrower.html"
});
when you go to localhost:8080/yourapp/borrower
and you need ng-view in your index.html
Like this
<div ng-view></div>
your pages will be shown here.
router will look that you are requesting for the borrower and it will take you to the /HTML/app/borrower.html
You are using html five mode that means you need server side routing to so it can fall to index.html every time so your url can be without hash.
I started a project form the Angular Seed Project. I've done a few Angular projects before, but this is the first one I have setup from scratch. I don't remember having to add new modules to the "app level module" before. Seems like there is a way to automate this, but my Google-Fu is failing me.
Basically, I'm looking for a way to remove 'myApp.home' and such from app.js so that I don't have to always add new pages to the app.js. I know some modules will need to go there, but adding every page there seems like a pain. I already figured out how to automate adding the script references to index.html
//////////////////// APP.JS ////////////////////
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', [
'ngRoute',
'myApp.home'
])
.config(['$locationProvider', '$routeProvider', function ($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.otherwise({ redirectTo: '/home' });
}]);
//////////////////// HOME.JS ////////////////////
'use strict';
angular.module('myApp.home', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/home', {
templateUrl: '../app/home/home.html',
controller: 'HomeCtrl'
});
}])
.controller('HomeCtrl', [function () {
}]);
<!---------- INDEX.HTML ---------->
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>My App</h1>
<div ng-view></div>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="app.js"></script>
<script src="home/home.js"></script>
</body>
</html>
<!---------- HOME.HTML ---------->
<div>TEST</div>
if you will not create a new module for each new page, but use myApp module, then you do not need to add it as dependency to the myApp module. Each page will have its own JS file:
//////////////////// HOME.JS ////////////////////
'use strict';
angular.module('myApp')
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/home', {
templateUrl: '../app/home/home.html',
controller: 'HomeCtrl'
}
);
}])
.controller('HomeCtrl', [function () {
}
]);
My scripts are :
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>My Application</title>
</head>
<body>
<div ng-view></div>
<script src="/assets/vendor/angular/angular-1.2.16.min.js"></script>
<script src="/assets/vendor/angular/extras/angular-route.js"></script>
<script src="/assets/myapp/myApp.js"></script>
</body>
</html>
myApp.js
(function () {
angular.module('myApp', ['ngRoute'])
.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
template: '<h1>Home</h1>',
controller: function () {
console.log('Home');
}
}).
when('/books', {
template: '<h1>Books</h1>',
controller: function () {
console.log('Books');
}
});
$locationProvider.html5Mode(true);
console.log('routes configured');
}]);
})();
I've wasted a lot of time trying to figure out what the problem might be with no luck. Am I missing something silly? thanks in advance for the help.
Are you hosting your application in the root of your server? If not, then you will need to use the tag below in your head tag.
<base href="PATH_HERE" />
In addition, can you comment out the $locationProvider.html5Mode(true) line and get your app working in hash routing mode first?
Just a question, but it is possible to add a function in the controller -> controller:function()? Because normally i would do it like this. controller:'mainController' and put the function in the mainController.