How to add active class inside header navigation directive inside a controller? - angularjs

Since my app has a navigation menu repeated in several pages, I made a directive for it. Now, the .active class isn't applied to current page anymore. Do I need to put the controller inside the directive?
Though not elegant, here's my code so far. Thanks.
page.html
<div class="app-container">
<div class="header clearfix">
<div ng-controller="NavmenuCtrl">
<nav-menu></nav-menu>
</div><!-- END NavmenuCtrl -->
</div><!-- /header -->
<div class="container"></div>
</div><!-- /app-container -->
navmenu directive
'use strict';
var app = angular.module('tempApp');
app.controller('NavmenuCtrl', function ($scope, $route) {
$scope.navMenuState = function($scope) {
$scope.navState = $route.current.navState;
};
});
app.directive('navMenu', function($route) {
return {
scope: {},
restrict: 'E',
replace: true,
templateUrl: 'views/partials/navmenu.html',
link: function navMenuState(scope, element, attrs, controller){
// Watch for the $location
scope.$watch(function() {
// do I need a scope.$watch?
}
};
});
navmenu.html partial
<div>
<div class="nav-container">
<ul class="navbar">
<li class="col-xs-5" ng-class="{ active:route.current.navState === 'pg1Active' }">
<a href="/#/pg1/">
<img src="images/icon1.png" class="center-block">
</a>
</li>
<li class="col-xs-5" ng-class="{ active:route.current.navState === 'pg2Active' }">
<a href="/#/pg2">
<img src="images/icon2.png" class="center-block">
</a>
</li>
</ul><!-- /.navbar -->
<div class="overflow-menu pull-right dropdown" ng-controller="NavDropdownCtrl">
<a class="dropdown-toggle">
<img ng-src="images/icon3.png">
</a>
<ul class="dropdown-menu">
<li ng-repeat="name in MenuItems">
<h4>
<a ng-href="#/{{ name | lowercase }}/">
{{name}}
</a>
</h4>
</li>
</ul>
</div><!-- /.overflow-menu -->
</div><!-- /.nav-container -->
</div>
app.js
'use strict';
angular.module('tempApp', [
...
])
.config(function ($routeProvider) {
$routeProvider
.when('/pg1/', {
templateUrl: 'views/pg1.html',
controller: 'MainCtrl',
navState: 'pg1Active'
})
.when('/pg2/',
{
templateUrl: 'views/pg2.html',
controller: 'MainCtrl',
navState: 'pg2Active'
})
I also found these related links:
Behavior of controller inside directives
AngularJS - Handle repeated fragments like Header and Footer
http://coder1.com/articles/angularjs-managing-active-nav-elements

You need to inject the $location service into your directive and check for routes there.

Related

angular-ui-tree doesn't work with more than 9 levels

I have a directive that use the angular-ui-tree component inside an asp.net mvc project, it works really great but a major bug appears every time it renders a tree with more than 9 levels.
For this we have an open issue, but is still not merged in master branch, anyway, I need to find a workaround, this is my code:
Directive:
(function () {
"use strict";
angular
.module("app.users")
.directive("columnConfigurationA", [
function () {
return {
restrict: "E",
scope: {
columnConfig: "=columnConfig"
},
link: {
pre: function (scope) {
}
},
controller: ["$http", "$scope", "$uibModal", "modalMsgSrv",
function ($http, $scope, $uibModal, modalMsgSrv) {
$scope.columnConfig = [];
$scope.carePlans = [];
getColumnConfiguration(params, $http).success(function (data) {
$scope.columnConfig = setVisibleColumns(-1, data.columns);
$scope.carePlans = data.carePlans;
});
}],
templateUrl: '/sbusA/ColumnConfigurationA'
};
}]);
function getColumnConfiguration(params, $http) {
var url = "/SbusA/GetColumnConfigurationA";
return $http.get(url, { params: params });
}
})();
HTML:
<div class="plan-edit-cont">
<div class="sorteable">
<script type="text/ng-template" id="nodes_renderer.html">
<div class="checkbox c-checkbox mb0 mt-sm inline align-top">
<label><input type="checkbox" ng-disabled="edition" ng-model="node.show" ng-click="disableChildrens(node)"><span class="fa fa-check"></span></label>
</div>
<div class="text-inverse inline" ui-tree-handle>
{{node.title}}
</div>
<a role="button" class="flow-icon-sort ml-lg mr fr drag-icon draggable" ng-hide="edition" dnd-handle><i class="fa fa-sort" aria-hidden="true"></i></a>
<a role="button" class="flow-icon-plus ml-lg fr drag-icon" ng-hide="edition" ng-click="editVital(node)"><i class="fa fa-pencil" aria-hidden="true"></i></a>
<ul class="sub-questions-list" ui-tree-nodes="" ng-model="node.columnChilds">
<li ng-repeat="node in node.columnChilds" ui-tree-node ng-include="'nodes_renderer.html'">
</li>
</ul>
</script>
<div ui-tree>
<ul style="list-style: none;" ui-tree-nodes="" ng-model="columnConfig" id="tree-root" dnd-list="columnConfig" dnd-allowed-types="['node']">
<li ng-if="node.visibleColumn === true" ng-repeat="node in columnConfig" ui-tree-node ng-include="'nodes_renderer.html'" dnd-draggable="node" dnd-type="'node'" dnd-moved="removeVital(node)"></li>
</ul>
</div>
</div>
</div>
This is the error that I get when I have more than 9 tree levels:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations:

Angular Directive - how to create a dynamic "page-options"

I have a div which appears in all the pages of my website.
I want to display it everywhere but with different data according to the current state (I'm using UI router for angular1)
So I decided I should use a directive.
pageoptions.html
<div class="page-options">
<!-- if state = 'dashboard' -->
<h1>Dashboard</h1>
<a ui-sref="restore">Some Action</a>
<a ui-sref="backup">Another Action</a>
<!-- if state = 'Edit' -->
<h1>Edit</h1>
<a ui-sref="restore">Delete</a>
<!-- if state = 'settings' -->
<h1>Settings</h1>
<a ui-sref="backup">Settings</a>
</div>
pageoptions-directive.js
myApp.directive('pageinfo', function() {
return {
restrict: 'A',
templateUrl: "./components/pageinfo/pageinfo.html"
};
});
But I don't know how to insert the logic that I wrote in comments in the HTML.
I would love to get some advice on this
You should be able to inject the $state service into your directive and use it in your markup to check the current state, using ng-hide or ng-show. Hopefully this gets you pretty close:
myApp.directive('pageinfo', ['$state', function($state) {
return {
restrict: 'A',
templateUrl: "./components/pageinfo/pageinfo.html"
link: function(scope) {
scope.currentState = $state.current.name;
}
};
});
template:
<div class="page-options">
<!-- if state = 'dashboard' -->
<div ng-show="currentState == 'dashboard'">
<h1>Dashboard</h1>
<a ui-sref="restore">Some Action</a>
<a ui-sref="backup">Another Action</a>
</div>
<div ng-show="currentState == 'Edit'">
<!-- if state = 'Edit' -->
<h1>Edit</h1>
<a ui-sref="restore">Delete</a>
</div>
<div ng-show="currentState == 'settings'">
<!-- if state = 'settings' -->
<h1>Settings</h1>
<a ui-sref="backup">Settings</a>
</div>
</div>
maybe this would help:
directive.js:
myApp.directive('pageinfo', function() {
return {
restrict: 'EA',
scope: {
state: '=' // if you want take a sting in directive , use '#'
},
templateUrl: "./components/pageinfo/pageinfo.html"
};
});
template.html:
<div class="page-options">
<!-- if state = 'dashboard' -->
<div ng-show="state == 'dashboard'">
<h1>Dashboard</h1>
<a ui-sref="restore">Some Action</a>
<a ui-sref="backup">Another Action</a>
</div>
<!-- if state = 'Edit' -->
<div ng-show="state == 'Edit'">
<h1>Edit</h1>
<a ui-sref="restore">Delete</a>
</div>
<!-- if state = 'settings' -->
<div ng-show="state == 'settings'">
<h1>Settings</h1>
<a ui-sref="backup">Settings</a>
</div>
</div>
use directive like this:
<pageinfo state="get your state and put it in here"></pageinfo>

Nested ui-view in angularjs

I am trying to do something here but it does not work, I have the following view:
<header ui-view="header">
</header>
and here is my app.js file:
.state('root', {
url: '',
views: {
'header': {
templateUrl: '/js/app/partials/layout/header.html',
controller: 'HeaderController'
},
'slider': {
templateUrl: '/js/app/partials/slider.html'
},
'container#': {
templateUrl: '/js/app/partials/home.html',
controller: 'HomeController'
},
'sidebar': {
templateUrl: '/js/app/partials/layout/sidebar.html',
controller: 'SideBarController'
},
'footer':{
templateUrl: '/js/app/partials/layout/footer.html'
}
}
})
Now this particular view:
'slider': {
templateUrl: '/js/app/partials/slider.html'
},
is not in my index.html file but rather within my /partial/layout/header.html file. Now the header template is being loaded into the header view, but the slider view does not show.
This is my header.html partial with my slider view inside:
<div class="container-fluid">
<div class="col-md-12">
<a href="#" class="pull-left">
<img src="images/logo.png" alt="Your Happy Family" class="img-responsive">
</a>
<!-- Begin Top Navigation -->
<div class="menu_block">
<nav class="horizontal-nav full-width horizontalNav-notprocessed">
<ul class="sf-menu">
<li class="home"><a ui-sref="root.home">home</a></li>
<li class="tickets">
tickets
<ul>
<li class="bus">Bus</li>
<li class="airline">Local Airline</li>
<li class="events">Events</li>
</ul>
<div class="clear"></div>
</li>
<li class="partners"><a ui-sref="root.partners">partners</a></li>
<li class="contact"><a ui-sref="root.contact">contact us</a></li>
</ul>
</nav>
<div class="clear"></div>
</div>
<!-- End Top Navigation -->
<div class="clear"></div>
<!-- Slider View -->
<div ui-view="slider">
</div>
<div class="clear"></div>
</div>
</div>
I am doing this for a reason, I need my slider view to appear within the header section.
What you usually need is relative pathing for multiple nested views. If you scroll down to the bottom of the docs (https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views) they explain what the syntax of relative pathing does.
This might be what you're looking for but I always get a little tripped up without actually testing the pathing and without a plunker...
'slider#root': {
templateUrl: '/js/app/partials/slider.html'
},

angular does not load my directive

I newly start to use angular.but I have some problem to loading my directive.
I want to load my directive as soon as page loaded.
where I load data-show directive
<div class="row">
<div class="col-md-12">
<article class="row" ng-controller="DataCtrl">
<input type="button" ng-click="getDataList()" >
<h1>Some Content Here</h1>
<ul id="home" bread-crumbs></ul>
<ul class="thumbnails">
<li ng-repeat="data in list" class="col-md-5">
<show-data data="data"/>
</li>
</ul>
</article>
</div>
</div>
showData directive:
app.directive('showData', function () {
return{
restrict: 'E',
replace:true,
templateUrl: 'views/directives/datas.directive.html',
scope: {
data: "="
},
controller:'DataCtrl'
}
})
and template I used in:
<div class="well hoverwell">
<div class="row">
<h2 class="col-md-4">{{data.name}}</h2>
</div>
<div class="row">
<span class="col-md-1">Code:</span>
<span class="col-md-1">{{data.id}}</span>
</div>
<div class="row">
<span class="col-md-1">accountability:</span>
<span class="col-md-1">{{data.parent}}</span>
</div>
<div class="row">
<span class="col-md-1"> :</span>
<span class="col-md-1">{{data.definition}}</span>
</div>
</div>
and my controller
'use strict';
angular.module('app')
.controller('DataCtrl', function ($scope, DataService, $log) {
$scope.getDataList = function () {
var list = DataService.getDataList(1);
list.then(
function (result) {
$log.info(result);
$scope.dataList = result;
}, function (status) {
$log.error(status)
$scope.msg = "error " + status + " has been occur,please report to admin ";
});
};
});
and when I run my app it does not work .
when I watch it in chorome development tools my directive is comment
what is my problem.How can I call this directive as soon as page load.
thx
As you already noticed, you see empty list because your dataList in ng-repeat is not filled yet.
But you have some errors in your code:
First of all - you should never use one controller twice. So you need to create separate controller for your directive.
replace directive parameter is deprecated, better not to use it.
In your DataCtrl you set the dataList variable: $scope.dataList = result;, but in HTML you refer to list variable: <li ng-repeat="data in list" class="col-md-5">.
Maybe that example will help you to figure out with your code.

angular-js 2 or 3 ng-view for slide

i need to add 2 o 3 slider to my page with angularjs by reading some json.
my code should be something like that:
<div class="wrapper">
<div id="navigation">...</div>
<div class="slider">
<ul class="painting">
<li>
<img src="img/01.jpg" height="240" width="237"/>
<h1>title</h1>
<h2>description</h2>
</li>
<li>...</li>
<li>...</li>
</ul>
</div>
<div class="slider">
<ul class="illustration">
<li>
<img src="img/01.jpg" height="240" width="237"/>
<h1>title</h1>
<h2>description</h2>
</li>
<li>...</li>
<li>...</li>
</ul>
</div>
<div class="footer"></div>
</div>
i code 2 template: one for the list of slide and one for the detail. I add ng-view to the first div.slider and when i click on the image, the details template is open inside the div.slider ..instead i need to clean all and print it inside the body.
By now, this is my index:
<div id="wrapper">
<div id="navigation">...</div>
<div id="portfolio" class="sliderCont first">
<div ng-view class="slider"></div>
</div>
<div class="sliderCont">
<div class="slider"></div>
</div>
<div class="sliderCont">
<div class="slider"></div>
</div>
<div class="sliderCont last">
<div class="slider"></div>
</div>
</div>
this is my list.html template:
<ul class="works">
<li ng-repeat="work in works">
<img src="{{work.thumbUrl}}" height="240" width="237"/>
<h1>{{work.testo1}}</h1>
<h2>{{work.testo2}}</h2>
</li>
</ul>
my controller.js:
function sliderListCtrl($scope, $http) {
$http.get('json/slider1.json').success(function(data) {
$scope.works = data;
});
}
function sliderDetailCtrl($scope, $routeParams, $http) {
$http.get('json/' + $routeParams.workId + '.json').success(function(data) {
$scope.work = data;
});
}
and in the end, my app.js:
angular.module('workList', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/works', {templateUrl: 'partials/work-list.html', controller: sliderListCtrl}).
when('/works/:workId', {templateUrl: 'partials/work-detail.html', controller: sliderDetailCtrl}).
otherwise({redirectTo: '/works'});
}]);
does anyone have any idea?
I am not sure if I understand your question, but reading the title, 2-3 ng-view, that is not possible.
You can only have one ng-view per application, which normally contains the application itself.
If you want to add partial templates, you can use ng-include which allow you to add all the templates you want inside others.
On the other hand, there is a ui-router project which have a different way to add templates to your views.

Resources