Angular routes and views and controllers - angularjs

I am trying to make a very simple app with routes and views, that displays a test text changing into "click" when a button is clicked.
I have an index.html file with an ng-view thats calls properly a test.html view. This view is supposed to use a testCtrl.js with a simple model.
But when it loads, the view seems to be called, but there is a problem with the scope, or the controller. When I click on a button the word test is supposed to become "click" but nothing happens.
here is the index.html
<body ng-app="simtoolbelt">
<div ng-view></div>
<script src="js/modules/angular-route.min.js"></script>
<script src="js/controllers/testCtrl.js"></script>
<script src="js/vendor/jquery.js"></script>
<script src="js/foundation.min.js"></script>
<script>
$(document).foundation();
</script>
here is the app.js handling the routes and views:
var simtoolbelt = angular.module('simtoolbelt', ['ngRoute']);
simtoolbelt.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/test', {
templateUrl: 'views/test.html',
controller: 'testCtrl'
}).
otherwise({
redirectTo: '/test'
});
}]);
The test controller:
simtoolbelt.controller('testCtrl', ['$scope', function($scope){
$scope.test = "test";
$scope.change = function($scope){
$scope.test = "Click";
};
}]);
And finally the test view:
<div ng-controller="testCtrl">
<h1 ng-model="test">Le {{test}} fonctionne</h1>
<button ng-click="change()">Click</button>
</div>
All of that is in a localhost, and I really have no clue of what it is I am mising... Thanks lot guys for any help you can give me !

Your function "change" takes the argument "$scope". In ng-click you call a method without arguments.
Remove the parameter from your change method:
$scope.change = function(){
$scope.test = "Click";
};
Furthermore, there is no need for the ng-model attribute in your h1 tag.

Try to change controller definition in your routing to "only controller name" like
simtoolbelt.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/test', {
templateUrl: 'views/test.html',
controller: 'testCtrl'
}).
otherwise({
redirectTo: '/test'
});
}]);
I have not test it yet but it should work.

Related

One route works but not other two (using AngularJS and RouteProvider)

AngularJS v1.7.4
I am new to AngularJS and creating a simple app but not sure why one route works (shows the static html from a partial file as well as {{message}} correctly), but the other two routes only show static html and not {{message}} which is being set using $scope.message.
Additionally errors such as
The controller with the name 'ContactController' is not registered.
and
The controller with the name 'AboutController' is not registered.
Are seen in the console when trying to go to 'Contact' and 'About' pages respectively.
For the three routes I have three html files and three controller files. I have made sure to include <body ng-app="gmsApp">.
Files are being loaded as
<script src="./js/bootstrap.bundle.min.js"></script>
<script src="./js/angular.js"></script>
<script src="./js/angular-route.js"></script>
<script src="./js/controllers/about.controller.js"></script>
<script src="./js/controllers/contact.controller.js"></script>
<script src="./js/controllers/home.controller.js"></script>
<link href="./css/bootstrap.min.css" rel="stylesheet" />`
Following advise from other posts I am using the 'regular' js files and not 'minified' versions of angular and angular-route.
The code in main html file is:
var app = angular.module("gmsApp", ['ngRoute', 'gmsApp.controllers']);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeController'
}).
when('/about', {
templateUrl: 'partials/about.html',
controller: 'AboutController'
}).
when('/contact', {
templateUrl: 'partials/contact.html',
controller: 'ContactController'
}).
otherwise({
redirectTo: '/home'
});
}]);
/js/controllers/home.controller.js
angular.module('gmsApp.controllers', [])
.controller('HomeController', function ($scope) {
$scope.message = 'Main page of the app';
});
/js/controllers/about.controller.js
angular.module('gmsApp.controllers', [])
.controller('AboutController', function ($scope) {
$scope.message = 'This is about us page';
});
/js/controllers/contact.controller.js
angular.module('gmsApp.controllers', [])
.controller('ContactController', function ($scope) {
$scope.message = 'Contact Us page ...';
});
/partials/home.html
<div ng-controller="HomeController">
<h3>Home page</h3>
<p>{{message}}</p>
</div>
/partials/about.html
<div ng-controller="AboutController">
<h3>About Us</h3>
<p>{{message}}</p>
</div>
/partials/contact.html
<div ng-controller="ContactController">
<h3>Contact Us</h3>
<p>{{message}}</p>
</div>
The error come from the fact that you are recreating your module in each of your controller. This line should be present in only one of your files (could be your main file):
angular.module('gmsApp.controllers', [])
Then in "/js/controllers/home.controller.js,"/js/controllers/about.controller.js" and "/js/controllers/contact.controller.js", you should use it like this:
angular.module('gmsApp.controllers')
Note that this time you don't use the "[]". The difference between the two is that here you will access the already created module.
From angularjs docs:
Beware that using angular.module('myModule', []) will create the
module myModule and overwrite any existing module named myModule. Use
angular.module('myModule') to retrieve an existing module.

Angular Modal Window not working for the life of me

I'm very new to Angular.js.
I've taken the necessary elements from this tutorial on modal windows within Angular.js: http://jasonwatmore.com/post/2016/07/13/angularjs-custom-modal-example-tutorial
Isolated, I can get this code to work, but after porting it to my website, I just can't get it to work.
In Jason's code, he has a file called index.controller.js, and although I've ported this file to my own page, I don't believe it's firing. Here's index.controller.js:
(function () {
angular
.module('app')
.controller('Home.IndexController', Controller);
function Controller(ModalService) {
var vm = this;
vm.openModal = openModal;
vm.closeModal = closeModal;
function openModal(id){
ModalService.Open(id);
}
function closeModal(id){
ModalService.Close(id);
}
}
})();
On my own page, I have all the controllers contained within app.js. Here's how it's laid out:
var app = angular.module('app', ['ngRoute', 'ui.router']);
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$urlRouterProvider.otherwise("/");
$stateProvider
.state('home', {
url: '/',
templateUrl: 'pages/main.html',
controller: 'mainController',
controllerAs: 'vm'
})
.state('screenings', {
url: '/screenings',
templateUrl: 'pages/screenings.php',
controller: 'Home.IndexController',
controllerAs: 'vm'
})
...
});
You can see that, in the second .state, I'm attempting to call on the index.controller.js file for this particular partial. For some reason, though, the code under screeningsController (down below) is the code that's firing.
Further down in the same app.js file, I have my controllers:
...
app.controller('screeningsController', ['$scope', '$log', function($scope, $log){
$scope.popup = function() {
// assign a message to the $scope
$scope.message = 'Hello World!';
// use the $log service to output the message in a console
$log.log($scope.message);
};
}]);
...
Is there any way I can somehow integrate what's in the index.controller.js file into my screeningsController in the app.js? I've been trying to get a modal window working on my site for about a week now. Any help is much appreciated.
Start by creating a controller with identifier Home.IndexController. Based on the route configuration this will instantiate when you navigate to "/screenings". Call the popup() function attached to $scope of Home.IndexController via a directive us ng-click for testing. As you have specified controllerAs make sure to reference controller properties and methods prefixed with vm..
You do not need both index.controller.js and app.js both loaded. It looks everything you'd need is defined in app.js, so just make sure that is being loaded in your application. Eventually you'd want to separate these into different files and/or modules as necessary.
Try the following:
Configuration:
var app = angular.module('app', ['ngRoute', 'ui.router']);
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$urlRouterProvider.otherwise("/");
$stateProvider
.state('home', {
url: '/',
templateUrl: 'pages/main.html',
controller: 'mainController',
controllerAs: 'vm'
})
.state('screenings', {
url: '/screenings',
templateUrl: 'pages/screenings.php',
controller: 'Home.IndexController',
controllerAs: 'vm'
});
...
});
Home.IndexController:
app.controller('Home.IndexController', ['$log', function($log){
var vm = this;
vm.message = '';
vm.popup = function() {
vm.message = 'foobar';
$log.log(vm.message);
}
}]);
Screenings Template:
<!-- Home.IndexController /screenings template -->
<div>
<button type="button" ng-click="vm.popup()"></button>
</div>
This also assumes you have ui-view specified somewhere in your main template like index.html or equivalent:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body ng-app="app">
<div ui-view></div>
<!-- Vendor and Custom scripts added here -->
</body>
</html>

Conditionally include sidebar and header in Angular App

On certain views I want a sidebar and header, and some I do not. Using AngularJS, what is the best approach to achieve this.
My current solution in mind is to use ng-if on the sidebar and header DIV, and in my Controllers, set a $scope variable to be set to true or false depending on the views I want the sidebar and header to appear.
A concrete example would be Youtube.com. On Youtube's homepage, notice there is a sidebar and a sub-header with the filters: "What to Watch" and "Music" in it. However, on any video page, the sidebar and sub-header doesn't exist. I want to achieve that in AngularJS.
index.html
<html ng-app="demoApp">
<body ng-controller="demoAppMainController">
<header>
<ng-include src="'./partials/mainHeader.html'"></ng-include>
<ng-include ng-if="showSubHeader" src="'./partials/mainSubHeader.html'"></ng-include>
</header>
<main>
<ng-view></ng-view>
</main>
</body>
</html>
discussionBoard.html
<div class="discussionBoard" ng-controller="DiscussionBoardController">
<h2>DiscussionBoard</h2>
</div>
controllers.js
var demoAppControllers = angular.module('demoAppControllers', []);
demoAppControllers.controller('demoAppMainController', ['$scope', function($scope) {
$scope.showSubHeader = true;
}]);
opinionLensControllers.controller('DiscussionBoardController', ['$scope', function($scope) {
$scope.showSubHeader = false;
}]);
Instead of doing it in controller level, I would configure that in route level. And will listen to the $routeChangeSuccess event and update the $rootScope.
demoAppControllers.config(function ($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'home.html',
controller: 'HomeController',
showHeader : true
}).
when('/about', {
templateUrl: 'discuss.html',
controller: 'DiscussionBoardController',
showHeader : false
}).
otherwise({
redirectTo: '/home'
});
}).
run(['$rootScope', function($rootScope) {
$rootScope.$on("$routeChangeSuccess", function(event, next, current) {
$rootScope.showHeader = next.$$route.showHeader;
});
}]);
In your templates, you can just use ng-if="showHeader". It will be easily maintainable I feel.
ng-if="showHeader == true" use like this
<ng-include ng-if="showHeader == true" src="'./partials/mainSubHeader.html'"></ng-include>

Error while defining an angularjs controller

I have an view (insight index.html) like that:
<body ng-app="mainApp" ng-controller="MainCtrl">
[...]
<div>{{status}} </div>
</body>
I start the App onDeviceReady:
angular.element(document).ready(function() {
angular.bootstrap(document);
});
I have this module:
var mainAppModul = angular.module('mainApp', ['ngRoute'])
.config(function ($routeProvider, $compileProvider) {
$routeProvider
.when('/', {
controller: MainCtrl,
template: '<h1> Main View {{ status }} </h1>'
});
$compileProvider.aHrefSanitizationWhitelist (/^\s*(https?|ftp|mailto|file|tel):/);
});
As far as I know, there are different ways to define a controller. One way is like that:
mainAppModul.controller('MainCtrl',['$scope', function ($scope)
{
$scope.status = "It works!";
}]);
The other one is like this:
function MainCtrl ($scope)
{
$scope.status = "It works!";
}
While the 1st Version results in [ng:areq] Argument 'MainCtrl ' is not a function, got undefined, the 2nd Version works fine.
Is there something I misunderstood in general?
ngRoute works in combination with ngView You won't need to specify the ng-controller in your templates, ngRoute takes care of that for you. When you have this:
var mainAppModul = angular.module('mainApp', ['ngRoute'])
.config(function ($routeProvider, $compileProvider) {
$routeProvider
.when('/', {
// controller: MainCtrl, // EDIT: needs to be a string of the controller name
controller: 'MainCtrl',
template: '<h1> Main View {{ status }} </h1>'
});
});
All you need is this:
<html ng-app="myApp">
<body>
<ng-view></ngview>
</body>
</html>
ngRoute will put the template of the specified route into ng-view and use the associated controller.
Note: ngRoute does not come with angular.js, you'll need the angular-route.js included as well.

communicate between angular controller and route controller

index.html
<body>
<div data-form-modal >
<form>
<input type='text' name='test'/>
<input type='submit' value='submit' ng-click='submit()'/>
//this submit() function is in mainCtrl
</form>
</div>
</body>
this is my route:
app.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'mainCtrl',
templateUrl: 'index.html'
})
.otherwise({
redirectTo: '/'
});
});
mainCtrl:
controller.mainCtrl = function(){
...
$scope.submit = function(){
alert(1)
}
}
form modal directive:
directive.formModal=function(){
return {
...
}
}
when I click the submit button, I try to call the submit() function in mainCtrl, but nothing heppend, I think its because the mainCtrl is a route controller and dosen't belong to any scope, and the formModal directive can't access the submit method.
I want the mainCtrl to handle the restful service and the formModal directive handle the form validation, but I dont know how to call method in mainCtrl from the formModal, and what is the relationship between the mainCtrl and the formModalCtrl?
edited:
I try to move the restful method to a service, and call the service method in formModal directive controller , it works fine, but I still need to access the mainCtrl in order to update the model so that the view can change accordingly.
What I've done is:
var app = angular.module('myApp', ['controllers'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/', {
controller: 'mainCtrl',
templateUrl: 'index.html'
}).
otherwise({
redirectTo: '/'
});
}]);
var controllers = angular.module('controllers', []);
Then:
// separate file
controllers.controller('mainCtrl', ['$scope'
function ($scope) {
// do stuff with $scope
}
]);
You can probably do app.controller('mainCtrl' ... instead and save a controllers variable. I just happened to get this working on my site this way.
Also, make sure you have an ng-app of myApp enclosing an element with ng-view (for routing to work).

Resources