How to update content based on sidebar in AngularJS - javascript

I asked a question yesterday How to do multiple views with Angular to support header and sidebar? and based on that question I was able to make some progress in having a header and a sidebar for my AngularJS App.
I've got a working fiddle here: http://jsfiddle.net/mcVfK/929/
The JS looks like this:
angular.module('app', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/header1', {
templateUrl: 'header1.html',
controller: DashboardCtrl
})
.when('/header2', {
templateUrl: 'header2.html',
controller: DashboardCtrl
})
.when('/dashboard',{
templateUrl: 'dashboard.html',
controller: DashboardCtrl
})
.when('/sidebar1',{
templateUrl: 'sidebarlink1.html',
controller: DashboardCtrl
})
.when('/sidebar2',{
templateUrl: 'sidebarlink2.html',
controller: DashboardCtrl
})
.otherwise({
redirectTo: '/header1'
});
}]);
function DashboardCtrl() {
}
This seems to work, however, I want to find out whether there is a way to avoid including sidebar.html on every link in the sidebar?
If you notice on the fiddle, I'm doing this:
<script type="text/ng-template" id="sidebarlink1.html">
<div ng-include="'sidebar.html'" id="sidebar"></div>
sidebar link 1 content - including sidebar
</script>
<script type="text/ng-template" id="sidebarlink2.html">
<div ng-include="'sidebar.html'" id="sidebar"></div>
sidebar link 2 content - including sidebar
</script>
So I'm including sidebar.html on every link in the sidebar. I'm wondering if there is a way to avoid this? Also, is there an Angular way to highlight which sidebar link is currently active?

You can move the sidebar include out and use a variable to determine in what route you want to see it. Check out this jsfiddle:
http://jsfiddle.net/mcVfK/931/
angular.module('app', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/header1', {
templateUrl: 'header1.html',
controller: DashboardCtrl,
resolve: {
hasSidebar: function($rootScope) {
$rootScope.hasSidebar = false;
return false; }
}
})

I recomend to use ui-router (What is the difference between angular-route and angular-ui-router?) instead of ngRoute. Lear about it if you are interested. And then use some ng-switch like this:
//Parent template
<script type="text/ng-template" id="sidebarlinkparent.html">
<div ng-include="'sidebar.html'" id="sidebar"></div>
<div ng-switch="$state.current.name">
<div ng-switch-when="sidebar1" ng-include="'sidebarlink1.html'"></div>
<div ng-switch-when="sidebar2" ng-include="'sidebarlink2.html'"></div>
</div>
</script>
//template sidebar 1
<script type="text/ng-template" id="sidebarlink1.html">
sidebar link 1 content - including sidebar
</script>
//template sidebar 2
<script type="text/ng-template" id="sidebarlink2.html">
sidebar link 2 content - including sidebar
</script>
Then change your templateUrl in route config to go at the parent template sidebarlinkparent.html on /sidebar1 and /sidebar2
Aswell you can use your actual ngRoute and change the ngSwitch condition with a controller scope var setted on routes or something like that
EDIT:
OPTION 2:
//Parent template
<script type="text/ng-template" id="sidebarlinkparent.html">
<div ng-include="'sidebar.html'" id="sidebar"></div>
<div ng-include="$state.current.name +'.html'"></div>
</script>
OPTION 3:
//Parent template
<script type="text/ng-template" id="sidebarlinkparent.html">
<div ng-include="'sidebar.html'" id="sidebar"></div>
<div ng-include="$state.params.include +'.html'"></div>
</script>
etc etc..

Related

Load view on button click with Angularjs in single page application

I am very new to AngularJS. This is my first project so please forgive me if my question is very basic.
I am created a page using simple HTML and put three button on it.
On these button click I want to load views in the lowel part of screen.
Index.html
<body ng-app="MyApp">
<div class="tab" ng-controller="TabControlController">
<button class="tablinks" onclick="openTab(event, 'Environments')" ng-click="Views/EnvironmentsView.html">Environments</button>
<button class="tablinks" onclick="openTab(event, 'SIT_Downloader')" ng-click="Views/SITDownloaderView.html">Download PCP Client</button>
<button class="tablinks" onclick="openTab(event, 'Users')">PCP Users</button>
</div>
<div id="Environments" class="tabcontent" ng-controller="environmentController">
<div>
<div ng-view></div>
</div>
</div>
<div id="SIT_Downloader" class="tabcontent" ng-controller="SITDownloaderController">
<div>
<div ng-view></div>
</div>
</div>
<div id="Users" class="tabcontent">
<div>
<div ng-view></div>
</div>
</div>
</body>
Bootstrap.js
var MyApp= angular.module('MyApp', ['ngRoute'])
.config(function($routeProvider) {
$routeProvider
.when('/',
{
templateUrl: 'Views/EnvironmentsView.html',
controller: window.environmentController
})
.otherwise({ redirectTo: '/' });
});
views are very simple as of now...
<h3>PCP Users</h3>
<p>This screen will be used to add/remove users</p>
Can anyone help me to understand what I am missing here or redirect me to some page with full example of this.
This is single page application.
You can try instead of calling a function onclick of a button ,just link the route with anchor tag
Maintain the routes in separate js file
like:
(function() {
'use strict';
angular.module('app.home').config(appRoutes);
appRoutes.$inject = ['$routeProvider', '$locationProvider'];
function appRoutes($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '../yourhtmlfile.html',
controller: 'controllerName',
resolve: {}
})
}
})();
Also you dont need to have multiple ng-view for each view
have a single ng-view
<div>
<div ng-view></div>
</div>
this helps in loading the html page when you click on the tag and loads the corresponding html file.
You have some problem in your sample.
1- change <button ng-click=".." ></button> to
you can use button also but you should crate a function that changes the current route to new route.
<button ng-click="changeRoute('/home')" >Home</button>
$scope.changeRoute = function(newRoute){
$location.path(newRoute);
}
2- wrong syntax for define controller in route.(put controller in each route)
3- Don't need to multiple ng-view
Demo

AngularJS states and dynamic templates based on criteria

I'm trying to use AngularJS + ui-router in my project, it is working tho but I am in the middle of a situation here...
I have a HOME state with url /, and that state needs to do the following:
When user is NOT logged in, I want to show a full page with a login form and some different index.html because I don't need some columns and stuff.
When the user IS logged, then the default index.html should be used so I can use my ui-view grid system with all the cool stuff when a user is logged (navbar, search forms and a lot more which are in index.html as they must be shown in every page).
In order to check if the user is logged I have a factory AuthFactory.isUserLogged()
This is what I have done but is not exactly what I want...
index.html
<div ng-cloak="" ng-if="$root.globals.currentUser">
<div class="ui fixed inverted menu">
<div class="ui container">
<a class="header item" href=""><img class="logo" src="">Dashboard</a>
<a class="item">Link</a>
<div class="right menu">
<div class="ui dropdown icon item">
{{ $root.me.username }}
<div class="menu">
Settings
<div class="divider"></div>
Logout
</div>
</div>
</div>
</div>
</div>
<div class="pusher">
<div class="full height">
<div class="ui main container" ui-view="mainContainer"></div>
</div>
</div>
</div>
<div ng-cloak="" ng-if="!$root.globals.currentUser" ui-view="mainContainer"></div>
As you can see, ui-view="mainContainer" is declared twice in the same index.html one for user logged and one when not ($root.globals.currentUser)
app.js
$stateProvider
.state('home', {
url: '/',
views: {
'mainContainer': {
templateUrl: 'views/main.html',
controller: 'HomeCtrl',
controllerAs: 'vm'
}
}
})
I know this isn't a good solution, that's why I am asking for a better one...
PS: It doesn't really matter which index.html I use, I just don't need whole markup in my not-logged-home, just a simple login form without navbar and stuff
EDIT:
This isn't working, even the console.log, it doesn't output anything
.state('home', {
url: '/',
views: {
'mainContainer': {
templateUrl: function (AuthFactory) {
if (AuthFactory.isUserLogged()) {
console.log("yep");
return 'views/main.html';
}
console.log("nope");
return 'views/login.html';
}
}
}
})
Make two different state for login and home. When user is not logged in call login state and after login home page. Only one on master page.
Then for later transition after login you need to define another on home html page.
$stateProvider
.state('login',
{
url: '/login',
templateUrl: "Account/Login.html",
controller: 'LoginController'
})
.state('home',
{
url: '/home',
templateUrl: "Home/Home.html",
controller: 'HomeController'
})

How to load/render nested UI-Views in UI-Router

I have an application with one page called index.html. This page is the main page inside the application which I load my partials into.
Here is my Index.html:
<body>
<!--<div id="view" ng-view></div>-->
<div id="view" ui-view></div>
</body>
I want to load a Partial into this but then a partial into the partial i have just added.
The partial i want to add in is called dashboard.html and should be called when /dashboard routing is hit. Then I want to load a partial into the UI-View inside dashboard.html.
I don't know what other information I would need to supply to make this happen?
EDIT:
.state('dashboard', {
url: '/dashboard',
templateUrl: 'partials/dashboard.html',
controller: 'dashboard'
})
.state('dashboard.item', {
//url: '/dashboard/calender',
templateUrl: 'partials/calender.html',
controller: 'aceTrackerDash'
})
Its good to define nested states for this purpose . When the application is in a particular state — when a state is "active" — all of its ancestor states are implicitly active as well. Below, when the "contacts.list" state is active, the "contacts" state is implicitly active as well, because it's the parent state to "contacts.list" . So all nested defined views are loaded in their proper position:
Example :
$stateProvider
.state('contacts', {
templateUrl: 'contacts.html',
controller: function($scope){
$scope.contacts = [{ name: 'Alice' }, { name: 'Bob' }];
}
})
.state('contacts.list', {
templateUrl: 'contacts.list.html'
});
<!-- index.html -->
<body ng-controller="MainCtrl">
<div ui-view></div>
</body>
<!-- contacts.html -->
<h1>My Contacts</h1>
<div ui-view></div>
<!-- contacts.list.html -->
<ul>
<li ng-repeat="contact in contacts">
<a>{{contact.name}}</a>
</li>
</ul>
Plunker : http://plnkr.co/edit/7FD5Wf?p=preview
Also take a look at this :
Angular-UI Router: Nested Views Not Working

AngularJs controller not getting called when a link is clicked

Currently, I'm working on an initial AngularJs app for an Admin Console for a database. I'm pretty new at Angular, so I've started off by modifying the phonecat tutorial. Basically, I've got a Jersey REST API that I need to make calls against in Angular. CORS is not the problem, they're both running on the same Tomcat.
The data structure is Projects have Groups within them.
I can redirect from Login to the Projects list page, the controller for getting the list of projects is called, and I can click a project and get the details page and its controller is called. But when I click a link from the project-details page and have it redirect to the groups-list page, the REST api call is never made (according to Chrome's network monitor.)
I'm rather confused because hypothetically it should be the exact same as the projects list.
Controllers:
phonecatControllers.controller('ProjectListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/project?show_hidden=true').success(function(data){
$scope.projects = data.hits.hits
});
$scope.orderprop='timeModified';
}]);
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
$scope.orderprop='timeModified';
}]);
phonecatControllers.controller('ProjectDetailCtrl', ['$scope', '$routeParams' ,'$http', function($scope, $routeParams, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/project/'+$routeParams.projectId).success(function(data){
$scope.project=data;
});
}]);
project-details.html:
<img ng-src="{{project._source.imageUrl}}" class="project">
<h1>{{project._source.name}}</h1>
<p>{{project._id}}</p>
<ul class="specs">
<a ng-href="#/groups" ng-click=>Group IDs</a>
<dd ng-repeat="group in project._source.groupIDs">{{proj._source.name}}
{{group.groupID}}
</dd>
</ul>
group-list.html
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<!--Sidebar content-->
Search: <input ng-model="query">
Sort by:
<select ng-model="orderprop">
<option value="name">Alphabetical</option>
<option value="dateModified">Newest</option>
</select>
</div>
<div class="col-md-10">
<!--Body content-->
<ul class='groups'>
<li ng-repeat="group in groups | filter:query | orderBy:orderprop" class="thumbnail">
<img ng-src=" {{group._source.imageUrl}}" alt="{{group._source.name}}">
{{group._source.name}}
<p>{{group._source.timeModified}}</p>
</li>
</ul>
</div>
</div>
</div>
app.js
'use strict';
/* App Module */
var phonecatApp= angular.module('phonecatApp', [
'ngRoute', 'phonecatControllers', 'phonecatFilters']
);
phonecatApp.config(['$routeProvider',
function($routeProvider){
$routeProvider.when('/projects',
{
templateUrl: 'partials/project-list.html',
controller: 'ProjectListCtrl'
}).when('/projects/:projectId', {
templateUrl: 'partials/project-detail.html',
controller: 'ProjectDetailCtrl'
}).when('/home', {
templateUrl: 'partials/login.html',
controller: 'LoginCtrl'
}).when('/groups',
{
templateUrl: 'partials/group-list.html',
controller: 'GroupListCtrl'
})
.otherwise({
redirectTo: '/home'
});
}]);
I've even tried to take an approach where the projectID is a routeParam (kind of like for Project details), but still no luck.
Let me know if you anything else to answer my question. I know it's going to be something so stupidly simple that a handprint will appear on my forehead. (From what I've seen, possibly a space where it's not supposed to be.)
Thanks!
<a href="#/groups/{{group._id}}" class="thumb"> should be <a ng-href="/groups/{{group._id}}" class="thumb">
Also <a ng-href="#/groups" ng-click=>Group IDs</a should not have an empty ngClick on it. It should look like <a ng-href="/groups">.
So basically just change the attribute of the link from href to ng-href and then remove the # symbol from the link.
You have:
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
$scope.orderprop='timeModified';
}]);
I would instead do this in your controller:
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http) {
$scope.function_name = function() {
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
}
$scope.orderprop='timeModified';
}]);
For your link that is within the HTML element possessed by the controller,
<a ng-href="/groups" ng-click="function_name()">Group IDs</a>
As it is, your AJAX call is just sitting there. You need to place it within a block where code is executed for it to be called, just like in any other case. In this case, you must place it within a function that serves as a callback tied to ng-click.

Wrap HTML to all templates/partials in angularjs but not in index.html not in partial.html

Current
index.html
<body>
<div id="container" >
<div id="modal" >
</div>
<div class="wrapper mobileWrapper">
<!-- ui-view contains visible(window) of webpage -->
<div ui-view=""></div>
</div>
</div>
</body>
header.html
<header>
Header
</header>
footer.html
<footer>
Header
</footer>
mainPage.html - partial/template
<div ng-include="'header.html'"></div>
<div> Current Page Contents </div>
<div ng-include="'footer.html'"></div>
I need to keep only <div ui-view=""></div> inside index.html and need to move remaining tags somewhere inside.
In the above example if I used ng-include then tags opened in header.html needs to be closed in header only.
Is there any alternative ideas
Edit: I got one solution
Before I'm using
// Before main.html loading
angular.module 'ngApp'
.config ($stateProvider) ->
$stateProvider
.state 'home',
url: '/'
templateUrl: 'app/views/main/main.html'
controller: 'MainCtrl'
// Problem Solved: before wrapped with wrapper.html
angular.module 'ngApp'
.config ($stateProvider) ->
$stateProvider
.state 'wrapper',
abstract: true,
templateUrl: 'app/views/main/wrapper.html'
.state 'wrapper.home',
url: '/'
templateUrl: 'app/views/main/main.html'
controller: 'MainCtrl'
Is there any way to wrap some html for all views.
not in index.html
and
not in main.html(partial)
Edit 2:
Before my states like
.state 'home',
.state 'about-us',
to wrap html I created on abstract state
.state 'wrapper',
abstract: true,
templateUrl: 'app/views/main/wrapper.html'
then I prefixed parent state(wrapper) to all other states
.state 'wrapper.home',
.state 'wrapper.about-us',
Is there any way to do it without creating a parent state(wrapper)

Categories