In AngularJS, can I use current route in ngSwitch outside of ngView - javascript

I am trying to change the page header depending on current view. The header is outside of ngView. Is that possible or do I need to put the header inside the view?
My code looks similar to this:
<div id="header">
<div ng-switch on="pagename">
<div ng-switch-when="home">Welcome!</div>
<div ng-switch-when="product-list">Our products</div>
<div ng-switch-when="contact">Contact us</div>
</div>
(a lot of unrelated code goes here)
</div>
<div id="content>
<div ng-view></div>
</div>

Give each route a name when you are defining it. Then inject $route into the controller, then have the controller publish it into the current scope. You can then bind the ng-switch to $route.current.name

You could inject the $location service and check $location.path(). http://docs.angularjs.org/api/ng.$location
JS:
function Ctrl($scope, $location) {
$scope.pagename = function() { return $location.path(); };
};
HTML:
<div id="header">
<div ng-switch on="pagename()">
<div ng-switch-when="/home">Welcome!</div>
<div ng-switch-when="/product-list">Our products</div>
<div ng-switch-when="/contact">Contact us</div>
</div>
</div>

Seems as it will be different controllers for header and content. Best way for communication between controllers is service. Another way - events. See Vojta answer.

A nice aproach for solving this is maybe to inject $route in your controller and then use it to grab the current route name.
app.controller('YourController', function($scope, $route){
$scope.pagename = $route.current.$$route.name;
});
And you have to name your routes like the following:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/product-list', {
templateUrl: 'views/product-list.html',
controller: 'ProductsController',
name: 'product-list'
}).
when('/home', {
templateUrl: 'views/home.html',
controller: 'HomeController',
name: 'home'
}).
otherwise({
redirectTo: '/'
});
}]);
So when you load a route,the controller will read the current route name and pass it to the view in your pagename variable. Then the view will pick it up and display the correct view as you need.
Hope it helps :)

Related

How to bootstrap component based angular 1 application?

Using angular 1.6, here are the components I need to have:
+-------------------+
|side| |
|bar | |
|... | view |
|... | |
|... | |
+-------------------+
side bar: placed on left. using ng-repeat and updates dynamically.
view: rest of the app. template is static but contents changes when click on side bar.
when the user clicks on each list <li> of side bar, it updates the view. only view content/model will change. not the html template.
Important: I just don't want to write a code in <body>. Would like to have sidebar in one html file and view in another associated with their controllers and render the whole app through ng-view in <body>.
The side bar updates dynamically so that I cannot specify state in config() for each.
any other standard architecture is appreciated.
As mentioned in the comments, there are multiple architecture and framework choices that can be made to implement the type of templating you're looking for. I'll provide a basic example based on something I've used in the past with angular, using ui-router and child/nested views.
Lets say you have an index.html like:
<body>
<div ui-view="header" class="header"></div>
<div ui-view="main" class="main"></div>
<div ui-view="footer" class="footer"></div>
</body>
The index page just has the layout for the most high level view, namely header, content and footer. If you have no need for header and footer, you can just ignore/remove it. Now the layout your are looking for, with a side bar on the left and the content on the right, will be placed within the main view. To do this lets declare another page which will define this structure, call it landing.html (use bootstrap for simplicity):
<div class="container-fluid">
<div class="row landingContainer">
<div class="col-md-2 col-sm-4 col-xs-3 sidebarSection">
<div class="row item" ng-click="landing.changePage('content1')">
<span>Show Content 1</span>
</div>
<div class="row item" ng-click="landing.changePage('content2')">
<span>Show Content 2</span>
</div>
<div class="row item" ng-click="landing.changePage('content3')">
<span>Show Content 3</span>
</div>
</div>
<div class="col-md-10 col-sm-8 col-xs-9 contentSection">
<div ui-view="content"></div>
</div>
</div>
</div>
You can think of this page as the root of your layout. The page is split into a left and right section using bootstrap columns. The left side contains the listing of all your content views. You can use li, i just prefer divs. The right side will be where the dynamic part of the page is, where the content will change based on the item selected in the side bar. Each component view is a child of the landing page, it inherits all the features of the parent and then adds its own content into the ui-view, similar to how landing.html added its content into the main ui-view. Now lets take a look at the ui-router config that makes all this work.
function routerConfig($stateProvider, $urlRouterProvider) {
$stateProvider
.state('landing', {
url: '/landing',
views: {
'header': {
templateUrl: 'app/components/header/headerPrivate.html',
controller: 'HeaderController',
controllerAs: 'header'
},
'main': {
templateUrl: 'app/landing/landing.html',
controller: 'LandingController',
controllerAs: 'dashboard'
},
'footer': {
templateUrl: 'app/components/footer/footer.html',
controller: 'FooterController',
controllerAs: 'footer'
}
}
})
.state('landing.content1', {
url: '/content1',
views: {
'content': {
templateUrl: 'app/content1/content1.html',
controller: 'Content1Controller',
controllerAs: 'content1'
}
}
})
.state('landing.content2', {
url: '/content2',
views: {
'content': {
templateUrl: 'app/content2/content2.html',
controller: 'Content2Controller',
controllerAs: 'content2'
}
}
})
.state('landing.content3', {
url: '/content3',
views: {
'content': {
templateUrl: 'app/content3/content3.html',
controller: 'Content3Controller',
controllerAs: 'content3'
}
}
})
$urlRouterProvider.otherwise('/');
}
Here you'll notice that the landing page route defines the configuration for the 3 main views, header, main and footer. The url path will be /landing. Then content1, content2 and content3 are defined as children by nesting them within landing using the dot notation: landing.content1. The url paths for each child will then resolve to /landing/content1, /landing/content2, landing/content3. So now anytime you navigate to those locations only the content for that specific child will be nested within the landing pages "content" ui-view and the remaining layout of the page stays the same.
For the sake of completion, this is how the landing controller might look:
function LandingController($state) {
var vm = this;
vm.changePage = function(page){
$state.transitionTo('landing.'+page, null, null);
}
}

Multiple views with angular

So I am trying to display multiple views in angular to help fix the footer problem I am having with this site I am building. I want to make sure that what I have been reading about and trying to mimic is making sense. This is what I have so far.
index.html
<!--Do not code below this line-->
<main ng-view="header"></main>
<main ng-view="body"></main>
<main ng-view="footer"></main>
routes.js file
angular.module('appRoutes', ['ngRoute'])
.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
views: {
'header': {
temmplateUrl: 'app/views/header.html'
},
'body': {
templateUrl: 'app/views/body.html'
},
'footer': {
templateUrl: 'app/views/footer.html'
}
}
})
I have it working where I have just one view and have my header and footer inside the index.html file but I saw that you can have multiple views and really just switch out the "body" view with other pages.
Any advice would be much appreciated. Thank you
To display multiple views you could use only ng-include.
See https://docs.angularjs.org/api/ng/directive/ngInclude for more ngInclude details.
Here is a example: (notice the wrap in single quotes)
<div id="header">
<div ng-include="'header.html'"></div>
</div>
<div id="content" ng-view></div>
<div id="footer">
<div ng-include="'footer.html'"></div>
</div>
Use ngRoute with ng-view to define a region (e.g div#content) where will be changed the dynamic content (as partial html).
See https://docs.angularjs.org/api/ngRoute/directive/ngView for more ngRoute details.
Good luck!
You can have just one ng-view.
You can change its content in several ways: ng-include, ng-switch or mapping different controllers and templates through the routeProvider.
Alternatively, use ui-router

In Angularjs with ui-router how to change hash without reloading controller but keeping subviews routing enabled

In short: my demo, how to have subviews? (without reloading page)
Longer:
I'm using snapscroll to provide different screens effect (demo). This directive doesn't support by default ui-router so I had to do it myself.
When you move the mouse wheel beforeSnap event event is triggered. I call ui-router $state.go to change URL hash. I don't reload the controller.
$scope.beforeSnap = function (snapIndex) {
$state.go('view' + snapIndex,{},{
notify:false,
reload:false,
location:'replace',
inherit:true
});
};
Routing is like
.state('main', {
url: '/',
templateUrl: 'views/screens.html',
controller: 'mainCtrl'
})
.state('view0', {
url: '/green',
templateUrl: 'views/screens.html',
controller: 'mainCtrl',
params: {'color': 'green', 'screenIndex': 0}
})
[...]
views/screens.html:
<div fit-window-height="" snapscroll="" snap-index="snapIndex" before-snap="beforeSnap(snapIndex)">
<div class="green"></div>
<div class="blue">
<!-- How to enable these subviews? -->
<!-- <a ui-sref="view0.a">Go to view0.a</a> -->
<!-- <a ui-sref="view0.b">Go to view0.b</a> -->
<div ui-view="view1"></div>
</div>
<div class="red"></div>
<div class="yellow">
<div ui-view="view3"></div>
</div>
</div>
You can see a codepen and a demo.
The issue is that I want to have subviews in some "screens" (colours divs), e.g: view1 and view3.
But I don't know how to do it without reloading the whole page. Subviews like:
/view1/a
/view1/b
/view3/a
/view3/b
/view3/c
Besides, I think screens would be better/cleaner being children of main main.view0, main.view1, etc.
I read about multiple named views in ui-router and nested states without success.

AngularJS coupling between view and controller

I have an AngularJS application in which I started off with my view files having the controller defined using the ng-controller directive.
myview.html
<div ng-controller="MyController">
<ul>
<li class="thumb" ng-repeat="item in items">
<span profile ng-click="getItem(item.id)"></span>
</li>
</ul>
</div>
However, I am now using routing and my controller is defined as part of my routeProvider configuration.
myview.html
<div>
<ul>
<li class="thumb" ng-repeat="item in items">
<span profile ng-click="getItem(item.id)"></span>
</li>
</ul>
</div>
router.js
.when('/homepage', {
templateUrl: 'templates/myview.html',
controller: 'MyController'
})
This works, but although at first it seemed like this was helping me to decouple my view from my controller, something feels off as I still have references to scope member variables in my view and these are tied to my controller.
Am I missing something here? What have I gained from specifying MyController in my routeProvider and not in my template?
For all practical purposes I don't believe you gained anything, except from conforming to the standard way of defining routes, views and controllers in AngularJS.
If we're thinking programming principles and MVC, your view now doesn't know anything about the controller, it is only dependent on the model (that'd be $scope in angular), which is fine and perfectly normal in a MVC-architecture.
By defining the controller in your route, you can use the same view (template) in multiple controller (and pass different scoped data)
For example:
.when('/homepage', {
templateUrl: 'templates/myview.html',
controller: 'MyController'
})
.when('/list', {
templateUrl: 'templates/myview.html',
controller: 'MyListController'
})

Angular JS Routing Issue

Below is my routing defined in html, this is defined in left pane
<a href="#loadApp" data-toggle="tab" >loadApp</a>
and page content is is right pane:
<div class="right-pane" id="rightPanel" >
<div ng-view>
</div>
</div>
when i click on url in left pane right gets refreshed.
It works fine when i click on it first time, my page gets loaded. but when i click on same url again my ng-view should get loaded again but that's not happening it remains same and nothing refreshes. Is there something that i am missing.
Routing configured as
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/loadApp', {
templateUrl: '../html/partials/centralPage.html'//,
}).
otherwise({
redirectTo: '/Default'
});
}]);
Thanks
Have you tried adding an ng-click to your top div? It likely isn't refreshing because the page isn't loading, try doing the following:
<div class="right-pane" ng-click="pageRefresh()" id="rightPanel" >
<div ng-view>
</div>
</div>
and in your controller:
app.controller('rightPaneCtrl', function() {
var pageRefresh = function() {
$scope.$apply();
});

Categories