Multiple controllers for a template using routeProvider - javascript

I'm starting to develop my first big project using AngularJS and while I was thinking about the design for the app, I found something that I don't understand.
I was thinking in a single-page app, so I'm using ng-view and routeProvider to route each query to the right template and controller. However, some of my templates are a bit complex and I first thought to use different controllers to manage each one. This is, different sections of the same template would be managed by different controllers. The problem (or at least, what I thought was the problem) is that routeProvider only lets to associate one template to one controller. This made me think that I could not use another controller for a template except the one I specified in routing configuration using routeProvider.
Then I started to figure out how to restructure the future project so I could maintain each different functionality in the same template being managed by a single controller and still let interact controllers between them.
After some headaches, I decided to try and implement my first approach to see how it failed and... What a suprise! It worked perfectly! But, I don't know exactly why.
Let me show you this simple example:
script.js
angular.module('myApp', [
'ngRoute'
])
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'main',
controller: 'MainCtrl'
});
$locationProvider.html5Mode(true);
});
angular.module('myApp')
.controller('MainCtrl', function ($scope) {
// whatever...
});
});
angular.module('myApp')
.controller('FirstCtrl', function ($scope) {
$scope.first = function(){
alert("First");
};
});
});
angular.module('myApp')
.controller('SecondCtrl', function ($scope) {
$scope.second= function(){
alert("Second");
};
});
});
main.html
<div ng-controller="FirstCtrl">
<button ng-click="first()">First!</button>
</div>
<div ng-controller="SecondCtrl">
<button ng-click="second()">Second!</button>
</div>
index.html
<body ng-app="myApp">
<div ng-view=""></div>
</body>
I thought if you configure the route to associate "main" template to "MainCtrl" controller, that would be the only controller interacting with the template, but it's not.
I first thought the "first" and "second" functions would not be found because "FirstCtrl" and "SecondCtrl" weren't declared in the routes configuration. I thought maybe routeProvider would be "wrapping" (or something like that) the "main" template and the "MainCtrl" controller, and "main" template would not have access to the rest of the controllers.
But that's not correct, the "first" and "second" functions from different controllers works correctly. So, what is the point in specifying a controller for a template in routes configuration? You could just set a template to render for a specified query and that template could use any controller of the module.
Maybe this is not a good design, I don't know.
Could you help me to understand this better?
Thanks!

When using $route provider as you're stating:
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'main',
controller: 'MainCtrl'
});
$locationProvider.html5Mode(true); });
You're actually wrapping everything within the './' route with MainCrtl.
Therefore when you inject the Main.html view in <div ng-view=></div> you get the following rendering:
<body ng-app="myApp">
<div ng-controller='MainCtrl'>
<div ng-controller="FirstCtrl">
<button ng-click="first()">First!</button>
</div>
<div ng-controller="SecondCtrl">
<button ng-click="second()">Second!</button>
</div>
</div>
</body>

Really, the point is just so you don't have to do <div ng-controller="MyCtrl"> in the view. This could have some advantages, like a view that may hold different data for different contexts but still be the same html.

Related

Multiple controllers on the same view

How can I call two or more controllers in the same view like this:
.when('/func', {
controller: 'ListController' ,
controller: 'AddController',
templateUrl: 'views/funcionario/func.html'
})
or this:
.when('/card', {
controller: ['ListController','AddController'],
templateUrl: 'views/cardapio.html'
})
You can't set two controllers in your route, but you could set one in your route and then use ng-controller to set another as part of your template.
For example:
.when('/card', {
controller: 'ListController',
templateUrl:'views/cardapio.html'
}
Then in your template:
<div ng-controller="AddController">
//part of html that you can to use AddController for
</div>
Its not generally recommended best practice to do this though.
You could do something like this:
<div ng-view></div>
<div ng-controller="SecondController"></div>
In the ng-view you would load your view/controller as defined in your $routeProvider and have the SecondController take care of the second div.

What attributes can I use in ngView to display the template for the current route?

I'm learning AngularJS and one of the assignments reads like this:
Now, add a new div tag to our index.html with an attribute directive that
will include the rendered template for the current route.
That is, I need to put something inside the following div, which will render the correct (according to routes) template.
<div class="main-wrapper">
</div>
In all examples that I could find, this task is solved by putting <ng-view/> into the HTML code.
But this answer is wrong.
How else can I implement it (render the template, which corresponds to the current route) ?
ngView directive can be used both as an element:
<ng-view></ng-view>
and as an attribute
<div ng-view></div>
See documentation
<ng-view/> is required from the ngRoute module. Templates may be resolved using $routeProvider as
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookCtrl',
controllerAs: 'book'
})
.when('/Book/:bookId/ch/:chapterId', {
templateUrl: 'chapter.html',
controller: 'ChapterCtrl',
controllerAs: 'chapter'
});
$locationProvider.html5Mode(true);
}])
If you want to manipulate your templates from the controller you could also use ngInclude. You still need to resolve your route inside your controller before fetching the proper template.

How to do load page in Angular JS?

How to load content on page by clicking on menu links?
For example, there is menu:
Personal
Contacts
Question is in how change template HTML in page for each link?
Basically what you are trying to achieve will be accomplish by creating SPA. For that you need to use ngRoute module in your application(by adding angular-route.js)
For setting up angular router you need to register routes with there template & controller, etc. inside app.config.$routeProvider would take a URL by .when method.
Code
var app= angular.module('app', ['ngRoute']);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/tab/:id', {
templateUrl: 'template.html',
controller: 'templateController'
}).
otherwise({
redirectTo: '/tab/1'
});
}]);
& then there would be one section on UI which is nothing but ng-view directive that watches of $routeProvider configuration with url in browser bar
<ng-view></ng-view>
For more details look at this answer
Working Example Plunkr
Additional to #pankaj, You have to use $location services in your controller. So that you can change view accordingly from controller.
ex. You have link
<a ng-click="saveData">Save</a>
Now in controller:
$scope.saveData = function(){
$location.href('viewName');
}
ref : https://docs.angularjs.org/api/ng/service/$location

best way of setting up 12 product pages in AngularJS with dynamic routing and templating

I'm somewhat new to AngularJS so I'd like to know whats the best way to architect the products section of my app.
So I have a main product page which will list and link to all my 12 products. Then each ind. product page will need to have the same format (i.e. product description, color, height etc.). This data will not be coming from a backend source. Its just plain HTML.
Whats the best way of setting things up to maximize code reuse? I'm thinking I want to do for the routing - /products/products.html to list all products and then something like /products/product1.html for an ind. product.
How can I make this all work in AngularJS?
Thanks!
For routing you will need to use the ng-view directive in your HTML. The simplest way I can think of is to create a div on the main page and assign it the directive ng-view. Then your Javascript file create a the routing. Below is a sample code just for reference purpose.
// YOUR HTML
<main class="cf" ng-view>
</main>
// YOUR JAVASCRIPT
var myApp = angular.module('myApp', ['ngRoute', 'appControllers']);
var appControllers = angular.module('appControllers', []);
myApp.config(['$routeProvider', function($routeProvider){
$routeProvider.
when("/products1", { templateUrl: "views/products1.html"}).
when("/products", { templateUrl: "views/products2.html"}).
when("/products3", { templateUrl: "views/products3.html"}).
otherwise({
redirectTo: "/login"});
}]);

AngularJS - UI-Routing - how to use the route state as variable in controller?

I am using Angular JS and UI-Routing. The routing works fine. My problem is showing and hiding a slider depending on what page the user is on.
My index.html looks something like this:
<body ng-app="myApp">
<header ng-include="'templates/header.html'"></header>
<div>Code for slider</div>
<!--=== Content Part ===-->
<div class="container">
<div class="row" >
<div ui-view autoscroll="false"></div>
</div>
</div><!--/container-->
<!-- End Content Part -->
<footer ng-include="'templates/footer.html'"></footer>
my app.js looks like this:
angular
.module('myApp', ['ui.router'])
.config(['$urlRouterProvider','$stateProvider',function($urlRouterProvider,$stateProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home',{
url: '/',
templateUrl: 'templates/home.html'
})
.state('about',{
url: '/about',
templateUrl: 'templates/about.html'
})
.state('contact',{
url: '/contact',
template: 'CONTACT'
})
}])
.controller()
Now I tried to include the slider in the home.html template but then it does not properly work due to initialisation requirements. When I use a controller in the different routes it is out of scope. So how do I pass a variable referring to the state to a controller indepent of the route so I can use it for it something like
if (state==home) {
$scope.showSlider==true;
}else{ $scope.showSlider==false;}
Thanks,
Gerd
UPDATE:
#Chris T
I have added this to my app.js:
.controller('myController',['$scope', '$state', function($scope,$state){
if ($state.includes('home')){
$scope.showIt=true;
}else{
$scope.showIt=false;
}
}])
Then I applied the controller to a div I wrapped around the slider and used
ng-show="showIt"
Inject $state into your controller. Then check if $state.includes("home");
Update:
I made a plunk with a parent state which controls the slider enabled/disabled based on $state.includes('main.home')
http://plnkr.co/edit/eT1MW0IU53qfca6sGzOl?p=preview

Categories

Resources