AngularJS view without controller - angularjs

I creating a simple angularjs app. I've imported ngRoute module and 2 views - Home and Contact. Home view is defined with controller.
.when("/", {
templateUrl: "home/home.html",
controller: "HomeController"
})
I don't need to implement logic for Contact view, because there are only 1 form to contact with me, that can work very well without angular. Can I define a route view without controller? Like:
.when("/contact". {
templateUrl: "contact/contact.html"
})
Is controller obligatory?

No controller is not obligatory. You can define a route without it

Related

Angular-js - dynamically create navi

I'm new to Angularjs and have sat through many tutorials to improve my knowledge. All tutorials show me how to use $routeProvider to load templates into view. However they only show me examples that assume the routes are known and I would like to learn how to dynamically create those routes so I can pull a list of unknown nav items from the db and create those routes in a loop.
So, typically a tutorial will show;
$routeProvider.when('/', {
templateUrl : 'views/home.html',
controller : 'mainController'
})
But what if I don't know what those routes will be in advance?
Unfortunately you can't create routes dynamically. You can only configure your routes in the module.config(). I think you search for routes with rest parameters.
Here an quick example with a list view and a detail view that shows one item of the list. Assume the backendService to be defined. The resulting url for the list is .../#/list and for the detail view of an item with the id 12345 the url is .../#/list/12345. Note that all route params are interpreted as strings. So routeParams will be {id: "12345"}.
In the angular phonecat step #9 is a good example of angular router.
angular.module('app').config( function($routeProvider) {
$routeProvider.when('/list',
{
templateUrl: 'views/list.html',
controller:'listCtrl'
}
).when('/list/:id',
{
templateUrl: 'views/detail.html',
controller: 'detailCtrl'
})
});
angular.module('app').controller('detailCtrl',
function($scope, $routeParams, backendService) {
$scope.items = backendService.getItemById($routeParams.id);
}
);

how to setup ui-router nested views

I am trying to setup my app with ui-router. I am familiar with basic nested views but I am wanting to do something more complex. I have my basic setup for the main views. I would like to have a chat popup that has its own views that are independent from the main views. I want to be able to navigate the main views and not affect the states in the chat popup. So how is this done? Do i need to have a abstract state for the chat? and then have nested views from there?
here is a visual.
and here is a plunker
plunker
$stateProvider
.state('root', {
abstract: true,
views: {
'#': {
template: '<ui-view />',
controller: 'RootCtrl',
controllerAs: 'rootCtrl'
},
'header#': {
templateUrl: 'header.html',
controller: 'HeaderCtrl',
controllerAs: 'headerCtrl'
},
'footer#': {
templateUrl: 'footer.html',
controller: 'FooterCtrl',
controllerAs: 'footerCtrl'
}
}
})
.state('root.home',{
parent:'root',
url:'/home',
templateUrl:'home.html',
controller: 'HomeController',
controllerAs:'homeCtrl'
})
.state('root.about',{
parent:'root',
url:'/about',
templateUrl:'about.html'
});
});
I suggest that, don't use footer as a ui-view, because it is completely independent of your states.
Then how?
Make your footer part as a template and use ng-include to render your footer part.
<footer ng-include="'/footer.html'"></footer>
And within footer.html you can specifies the controller for the footer view.
Benefits
No need to handle footer on each state
No need to pass chat history on every change in state.
Create Chat service/function with controllers in different js files and inject to the index.html and script.js. use bootstrap collapsible modal for pop-up chats.
Looking # your plunkr, you're on right track,though injecting controller from script.js via controllerAs is not scalable for larger app.
Instead you can create js files for each controller and service and separate partial views, just need to inject the services and controllers to index.html and mention partial views in stateprovider function.
I am not sure if You want to use route for the chat but there are two ways for you may be more
Use modals that can collabse and open when clicked like that of facebook here
Modals for bootstrap
Use angulars ngHide ngShow
For your navigation while using at sub elements on chat you can create one state for the chat and nest chat navigation in to you chat state so that any state change will not change your other chat states.
That means you will need to use substate concepts of ui-router

Displaying separate data from API in different places on page in Angular

I have a SPA that will display data from an API in two separate parts of the page. One section displays products and prices. This information will remain on the page. The other section is a basic CRUD view. It allows the user to create new selections, read their selections, edit their selections, and remove their selections. I'm trying to determine the best way to display these two views. The CRUD section uses ng-view. Should the price/product section use a directive, a separate controller, or should I break up the page into two modules?
I'm new to Angular, and want to make sure that I do things right to avoid unforeseen issues down the road.
HTML:
<div ng-view="">
<!--user selections go here -->
</div>
<!--Product/Price info will go here. Unsure whether to insert ng-app="new module", ng-controller="new controller", or a directive with its own element-->
Javascript for user selections view:
myApp.config(function ($routeProvider) {
$routeProvider
.when('/list', {
templateUrl: 'views/list.html',
controller: 'ProjectListCtrl as projectList'
})
.when('/edit/:projectId', {
templateUrl: 'views/detail.html',
controller: 'EditProjectCtrl as editProject'
})
.when('/new', {
templateUrl: 'views/detail.html',
controller: 'NewProjectCtrl as editProject'
})
.otherwise({
redirectTo: '/'
});
});
Factory for CRUD / user form section:
myApp.factory('Projects', function($firebase, fbURL) {
return $firebase(new Firebase(fbURL+'/projects')).$asArray();
});
Factory for product list/price section:
myApp.factory('Products', function($firebase, fbURL) {
return $firebase(new Firebase(fbURL + '/products')).$asArray();
});
The native Angular router is limited when creating complex and nested UIs, but AngularUI Router is a great alternative and very widely used. If you want to include multiple views in your interface then this is the way to go. It's not much more complicated than the native router but the wins are huge.
AngularUI Router is a routing framework for AngularJS, which allows you to organize the parts of your interface into a state machine. Unlike the $route service in the Angular ngRoute module, which is organized around URL routes, UI-Router is organized around states, which may optionally have routes, as well as other behavior, attached.
Here's a Plunker to demo your particular case: http://plnkr.co/edit/xZD47L?p=preview
With ui-router you can name views
<div ui-view="viewName"></div>
and include templates and controllers in the corresponding ui-router configuration
myApp.config(function($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /
$urlRouterProvider.otherwise("/");
$stateProvider
.state('home',{
url: "/",
// list your views
views: {
"viewName": {
templateUrl: "viewName.html" ,
controller: "viewNameCtrl"
}
}
})
});
Checkout this Wiki for Multiple Named Views.
I hope this helps.

angularjs routing based on conditions case statements

I have a different requirement for my angularJS views.
I have a cart running where an individual can checkout with 0$ as well ( some free gifts )
So, for the payment page view we came up with a different idea.
if($cart_total>0){
show payment page view;
} else {
show confirmation page view;
}
so how do I do the same in angularJS routing. My angular routing looks like this
as.config(function($routeProvider, $httpProvider) {
$routeProvider
.when('/index', {templateUrl: 'partials/index.html', controller: 'IndexListCtrl'})
.when('/shop/:id', {templateUrl: 'partials/shop.html', controller: 'ShopCtrl'})
.when('/payment/:id', {templateUrl: 'partials/payment.html', controller: 'PaymentCtrl'})
.when('/confirm', {templateUrl: 'partials/confirm.html', controller: 'ConfirmCtrl'})
.otherwise({redirectTo: '/index'});
});
So I need to show payment view only when cart_total > 0 else show confirm view.
Please help !!!
I think you have to use $route service events
PS. Here is similar question
First add a definition to your routes by declaring a constant like that.
angular.module("App")
.constant('Cart', {
showCart : 'true'
});
.when('/payment/:id',{
templateUrl:'',
access:Cart.showCart
})
Then you have to options. First in the run function check '$rootScope.$on('$locationChangeStart' event and inside it you can access the route by var location = $location.path(); var route = $route.routes[location];and then access the user role by route.access; then you can remove or add Html components.Or you can make a simple directives that dose the same route checking and use the link function to remove or add Html component

AngularJS: Multiple views with routing without losing scope

I'm trying to implement a classic list/details UI. When clicking an item in the list, I want to display an edit form for that item while still displaying the list. I'm trying to work around Angular's 1-view-per-page limitation and decided to do it by having all URLs routed to the same controller/view. (Perhaps this is the root of my problem and I'm open to alternatives.)
Routing:
$routeProvider
.when('/list', { templateUrl: '/Partials/Users.html', controller: UserController })
.when('/edit/:UserId', { templateUrl: '/Partials/Users.html', controller: UserController })
.otherwise({ redirectTo: '/list' });
The view (/Partials/Users.html):
<!-- List of users -->
<div ng-repeat="user in Users">
Edit {{ user.Name }}
</div>
<!-- Edit form -->
<div>
{{ SelectedUser.Name }}
</div>
Controller:
function UserController($scope, $routeParams) {
// the model for the list
$scope.Users = GetUserListFromService();
// the model for the edit form
if ($routeParams.UserId != null)
$scope.SelectedUser = GetUserFromService($routeParams.UserId);
}
Problems:
When clicking an edit link, the controller is reinstantiated with a new scope, so I have to re-init the Users list. (In a more complex example I could have input from the user stored bound to the model and this would also get lost.) I'd prefer to persist the scope from the previous route.
I'd prefer to use a separate controller (or, as many other Angular developers have complained, the ability to have multiple displayed views!) but that leads to the same issue of losing scope.
Try using ui-router: http://github.com/angular-ui/ui-router.
They have nested views and easier state management than angular default routing :-)
Multiple views are not supported in core AngularJS. You can use this library for this purpose which supports any amount of nested views on the page, where each level is configured independently with its own controller and template:
http://angular-route-segment.com
It is much simpler to use than ui-router. Sample config may look like this:
$routeSegmentProvider.
when('/section1', 's1.home').
when('/section1/prefs', 's1.prefs').
when('/section1/:id', 's1.itemInfo.overview').
when('/section1/:id/edit', 's1.itemInfo.edit').
when('/section2', 's2').
segment('s1', {
templateUrl: 'templates/section1.html',
controller: MainCtrl}).
within().
segment('home', {
templateUrl: 'templates/section1/home.html'}).
segment('itemInfo', {
templateUrl: 'templates/section1/item.html',
controller: Section1ItemCtrl,
dependencies: ['id']}).
within().
segment('overview', {
templateUrl: 'templates/section1/item/overview.html'}).
segment('edit', {
templateUrl: 'templates/section1/item/edit.html'}).
up().
segment('prefs', {
templateUrl: 'templates/section1/prefs.html'}).
up().
segment('s2', {
templateUrl: 'templates/section2.html',
controller: MainCtrl});
I've found Angular Multi View to be a godsend for this scenario. It lets you preserve scope as the route changes and lets multiple controllers share the same route without nesting your views.
I recommend Angular Multi View if you have more than 2 views on your page. Otherwise, when using ui-router, nesting multiple views gets messy really fast.
I came up with the same problem and I personnaly don't like plugins when they aren't absolutely unavoidable. I just moved singleton part to a service.
In my case there are :id[/:mode] routes and I want to react different way if user changes just mode or id too. Thus, I have to know previous id.
So, there is a service with activate method which updates its state. And the scope is reinitialized every time with the following code.
module.controller('MyController', ['$scope', '$routeParams', 'navigator', function($scope, $routeParams, navigator) {
var id = null;
var mode = null;
if (typeof($routeParams.id)!='undefined')
{
id = $routeParams.id;
}
if (typeof($routeParams.mode)!='undefined')
{
mode = $routeParams.mode;
}
navigator.activate(id, mode);
$scope.items = navigator.items;
$scope.activeItem = navigator.activeItem;
$scope.modes = navigator.modes;
$scope.activeMode = navigator.activeMode;
}]);
In activate method I can compare id to the singleton's activeItem.id and react differently.

Resources