Directive changes CSS when element is active - javascript

I'm very new to Angular so I'm sure this isn't correct but I have a set of <li> elements which further contain links (individually, they're just navigation buttons for my page). What I'd like is to keep the specific button, say, "Home" highlighted a certain color while the user is on that page. So my html roughly looks like this...
<li class="active menuBar">
<a ui-sref="aap.configure.views" change-css="aap.isActive()">
<div class="row text-center">
<span class="glyphicon glyphicon glyphicon-cog" aria-hidden="true" style="font-size: 2.5em;"></span>
</div>
<div class="row">
<span class="glyphicon-class">Home</span>
</div>
</a>
</li>
I literally just wrote my first custom Directive yesterday so here's my second attempt at one...
app.directive( 'changeCss', [ '$location',
function ( ) {
return {
restrict: 'A',
scope: {
active: '&'
},
link: function( $scope, element, attrs ){
if( $scope.active ){
element.addClass( 'actives');
}
else {
element.addClass( 'inActives' );
}
}
};
}
] );
And my isActive() function looks like...
var active = false;
$scope.aap.isActive = function( ){
if ( active ){
active = false;
return true;
} else {
active = true;
return false;
};
};
Now, when I load up the page all the navigation buttons (Home, Save, etc.) are the color I'd like them to be. Clicking on a button, say, "Home" highlights that button in the color I'd like it to be. But, when I interact with that Home page at all, click an accordion element for instance, the color goes back to the "inactive" color. What am I doing wrong?

I'm not 100% sure for this. but I hope this might help you. If you want to set the active/inactive of your navigation bar base on your page.
I use ng-class for setting active of the navigation bar (see here https://docs.angularjs.org/api/ng/directive/ngClass) by passing the uri to the function getClass().
<div class="col-sm-3 col-md-2 sidebar" ng-controller="mainCtrl">
<ul class="nav nav-sidebar">
<li ng-class="{'active': getClass('/dashboard')}" >
<a href="/">
Dashboard
</a>
</li>
<li ng-class="{'active': getClass('/session')}">
<a ng-href="/session">
Sessions
</a>
</li>
</ul>
</div>
at my Controller I check the location path and sends boolean for activating/deactivating the ng-class
.controller('mainCtrl', ['$location','$scope', function ($location, $scope) {
$scope.getClass = function(path) {
if ($location.path().substr(0, path.length) == path) {
return true;
} else {
return false;
}
}
}]);

Related

in ng-show not working while clicking reply link

<html lang="en" ng-app=“myDiscuss">
<head><!-- all the script files-->
</head>
<body>
<div class="thumbnail" ng-controller="TabController as tabs”>
<!-- some other div-->
<div ng-show="tabs.isSelected(1)">
<small>No of likes</small>
</div>
<section class="caption" >
<ul class="nav nav-pills">
<li ng-class="{ active:tab === 1 }" >
<a href ng-click="tabs.selectTab(1)">Helpful</a>
</li>
<li ng-class= "{ active:tab === 2 }">
<a href ng-click="tabs.selectTab(2)">Comment</a>
</li>
</ul>
<div class="panel" ng-show="tabs.isSelected(2)">
<blockquote>
<ul class="nav nav-pills">
<li ng-class="{ active:tab === 3 }" >
<a href ng-click="tabs.selectTab(3)" >Helpful</a>
</li>
<li ng-class= "{ active:tab === 4}">
<a href ng-click="tabs.selectTab(4)">Reply</a>
</li>
</ul>
<input type="text" ng-show="tabs.isSelected(4)">
</blockquote>
</div>
</section>
</div>
</body>
</html>
JavaScript File
var app = angular.module("myDiscuss", []);
app.controller("TabController", function() {
this.tab=0;
this.selectTab = function(setTab) {
this.tab= setTab;
};
this.isSelected = (function(checkTab){
return this.tab === checkTab;
});
});
When I click the "Comment" Link it open the div "panel". whereas when i click "Reply" link it doesn't open input tag.
Image with comment and helpful link
The div "panel" which open when comment link is clicked
Actually, it's working but since you are using same this.tab variable it's not working. You should take separate variable.
Take separate variable for main tabs & sub tabs or you can use another method to separate main tabs & sub tabs. Like 1.1 or 3.3 etc. There are many ways.
this.tab=0;
this.subTab = 0;
this.selectTab = function(setTab) {
this.tab= setTab;
};
this.selectSubTab = function(setTab){
this.subTab = setTab;
};
this.isSelected = (function(checkTab){
return this.tab === checkTab;
});
this.isSelectedSub = (function(checkTab){
return this.subTab === checkTab;
});
check the https://plnkr.co/edit/leTBpJUVC7giDCs9KtQX
For less confusion, I'd recommend assigning the controller to a variable:
var app = angular.module("myDiscuss", []);
app.controller("TabController", function() {
var v = this;
v.tab=0;
v.selectTab = function(setTab) {
v.tab= setTab;
};
v.isSelected = (function(checkTab){
return v.tab === checkTab;
});
});
This is because in function, this refers to the function, not the controller. By using a separate variable, you avoid the inconsistency.
Even the alias you're using, TabController as tabs, uses the same thing:
$scope.tabs = this internally.

AngularJS: Displaying data through a click action in a new page from a speific JSON file

I have a thumb-nail view of two images and I have two JSON files(named dataOne.json and dataTwo.json). When the user click on one of the images, I want to list out all the elements of the respective JSON file into a new web page. The new web page has a pill.
HTML:
<div id = "Cities" class = "neighborhood-guides">
<div class = "container" ng-controller="CityController">
<div class = "thumbnail" ng-click = "city(dataOne)">
<image src = "Images/NYC.jpg"/>
</div>
<div class = "thumbnail" ng-click = "city(dataTwo)">
<image src = "Images/LA.jpg"/>
</div>
</div>
</div>
HTML(new) :
<div class = "content" id = "content">
<div class="list-group-item">
<section class="tab" ng-controller = "TabController as tab">
<ul class="nav nav-pills">
<li ng-class="{ active: tab.isSet(1) }">
<a ng-click = "tab.setTab(1)" href>Categories</a>
</li>
<li ng-class="{ active: tab.isSet(2) }">
<a ng-click = "tab.setTab(2)" href>Interactive Guide</a>
</li>
<li ng-class="{ active: tab.isSet(3) }">
<a ng-click = "tab.setTab(3)" href>List of all places</a>
</li>
</ul>
<div ng-show = "tab.isSet(1)"></div>
<div ng-show = "tab.isSet(2)">
<blockquote>This is where I want the data</blockquote>
</div>
<div ng-show = "tab.isSet(3)">
<blockquote></blockquote>
</div>
</section>
</div>
</div>
app.js
function() {
var app = angular.module('app', []);
app.controller('CityController', function(){
$scope.city = function(param) {
$http.get(param+'.json', param).success(
function(data){
//What should I do here?
console.log(data);
}
).error();
}
});
app.controller('TabController', function(){
this.tab = 1;
this.setTab = function(newValue){
this.tab = newValue;
};
this.isSet = function(tabName){
return this.tab === tabName;
};
);
How do I get the data from the json file, through the click from page 1 and display it in the pill 2 of the new page?
you can define a service factory which holds the json data. please take a look this answer for similar question:
https://stackoverflow.com/a/21920241/4213391

Ionic hiding elements until scroll event

I am conditionally showing and hiding elements in my app in an accordion like fashion (can be seen in this video).
The code to perform this is:
<div class="filter-menu" ng-repeat="group in Filters | orderBy: 'title'">
<div class="filter-menu-titles" ng-click="toggleGroup(group)" ng-class="{active: isGroupShown(group)}">
<i class="icon energized" ng-class="isGroupShown(group) ? '{{group.icon}}-active' : '{{group.icon}}'"></i> <span class="filter-title-text" ng-class="{orange: isGroupShown(group)}"> {{group.title}}</span>
</div>
<div class="ion-checkbox-viewport">
<span class="filter-header" ng-show="isGroupShown(group)">{{group.title}}</span>
<br />
<ion-checkbox ng-repeat="filter in group.filters | orderBy: 'name'" class="item-accordion" value="{{filter.name}}" ng-model="filter.checked" ng-change="ModifyFilter(filter)" ng-show="isGroupShown(group)">
{{filter.name}}
</ion-checkbox>
</div>
</div>
And in the controller:
$scope.toggleGroup = function(group) {
if ($scope.isGroupShown(group)) {
$scope.shownGroup = null;
} else {
$scope.shownGroup = group;
}
};
$scope.isGroupShown = function(group) {
return $scope.shownGroup === group;
};
This works perfectly on the first load of the view. However when I navigate away from the view and then come back the elements that are shown and hidden conditionally are all hidden until a scroll event is performed. When scrolling occurs the elements are shown again.
This only occurs on iOS.

How do I toggle an ng-show in AngularJS based on a boolean?

I have a form for replying to messages that I want to show only when isReplyFormOpen is true, and everytime I click the reply button I want to toggle whether the form is shown or not. How can I do this?
You just need to toggle the value of "isReplyFormOpen" on ng-click event
<a ng-click="isReplyFormOpen = !isReplyFormOpen">Reply</a>
<div ng-show="isReplyFormOpen" id="replyForm">
</div>
Basically I solved it by NOT-ing the isReplyFormOpen value whenever it is clicked:
<a ng-click="isReplyFormOpen = !isReplyFormOpen">Reply</a>
<div ng-init="isReplyFormOpen = false" ng-show="isReplyFormOpen" id="replyForm">
<!-- Form -->
</div>
If based on click here it is:
ng-click="orderReverse = orderReverse ? false : true"
It's worth noting that if you have a button in Controller A and the element you want to show in Controller B, you may need to use dot notation to access the scope variable across controllers.
For example, this will not work:
<div ng-controller="ControllerA">
<a ng-click="isReplyFormOpen = !isReplyFormOpen">Reply</a>
<div ng-controller="ControllerB">
<div ng-show="isReplyFormOpen" id="replyForm">
</div>
</div>
</div>
To solve this, create a global variable (ie. in Controller A or your main Controller):
.controller('ControllerA', function ($scope) {
$scope.global = {};
}
Then add a 'global' prefix to your click and show variables:
<div ng-controller="ControllerA">
<a ng-click="global.isReplyFormOpen = !global.isReplyFormOpen">Reply</a>
<div ng-controller="ControllerB">
<div ng-show="global.isReplyFormOpen" id="replyForm">
</div>
</div>
</div>
For more detail, check out the Nested States & Nested Views in the Angular-UI documentation, watch a video, or read understanding scopes.
Here's an example to use ngclick & ng-if directives.
Note: that ng-if removes the element from the DOM, but ng-hide just hides the display of the element.
<!-- <input type="checkbox" ng-model="hideShow" ng-init="hideShow = false"></input> -->
<input type = "button" value = "Add Book"ng-click="hideShow=(hideShow ? false : true)"> </input>
<div ng-app = "mainApp" ng-controller = "bookController" ng-if="hideShow">
Enter book name: <input type = "text" ng-model = "book.name"><br>
Enter book category: <input type = "text" ng-model = "book.category"><br>
Enter book price: <input type = "text" ng-model = "book.price"><br>
Enter book author: <input type = "text" ng-model = "book.author"><br>
You are entering book: {{book.bookDetails()}}
</div>
<script>
var mainApp = angular.module("mainApp", []);
mainApp.controller('bookController', function($scope) {
$scope.book = {
name: "",
category: "",
price:"",
author: "",
bookDetails: function() {
var bookObject;
bookObject = $scope.book;
return "Book name: " + bookObject.name + '\n' + "Book category: " + bookObject.category + " \n" + "Book price: " + bookObject.price + " \n" + "Book Author: " + bookObject.author;
}
};
});
</script>
If you have multiple Menus with Submenus, then you can go with the below solution.
HTML
<ul class="sidebar-menu" id="nav-accordion">
<li class="sub-menu">
<a href="" ng-click="hasSubMenu('dashboard')">
<i class="fa fa-book"></i>
<span>Dashboard</span>
<i class="fa fa-angle-right pull-right"></i>
</a>
<ul class="sub" ng-show="showDash">
<li><a ng-class="{ active: isActive('/dashboard/loan')}" href="#/dashboard/loan">Loan</a></li>
<li><a ng-class="{ active: isActive('/dashboard/recovery')}" href="#/dashboard/recovery">Recovery</a></li>
</ul>
</li>
<li class="sub-menu">
<a href="" ng-click="hasSubMenu('customerCare')">
<i class="fa fa-book"></i>
<span>Customer Care</span>
<i class="fa fa-angle-right pull-right"></i>
</a>
<ul class="sub" ng-show="showCC">
<li><a ng-class="{ active: isActive('/customerCare/eligibility')}" href="#/CC/eligibility">Eligibility</a></li>
<li><a ng-class="{ active: isActive('/customerCare/transaction')}" href="#/CC/transaction">Transaction</a></li>
</ul>
</li>
</ul>
There are two functions i have called first is ng-click = hasSubMenu('dashboard'). This function will be used to toggle the menu and it is explained in the code below. The ng-class="{ active: isActive('/customerCare/transaction')} it will add a class active to the current menu item.
Now i have defined some functions in my app:
First, add a dependency $rootScope which is used to declare variables and functions. To learn more about $roootScope refer to the link : https://docs.angularjs.org/api/ng/service/$rootScope
Here is my app file:
$rootScope.isActive = function (viewLocation) {
return viewLocation === $location.path();
};
The above function is used to add active class to the current menu item.
$rootScope.showDash = false;
$rootScope.showCC = false;
var location = $location.url().split('/');
if(location[1] == 'customerCare'){
$rootScope.showCC = true;
}
else if(location[1]=='dashboard'){
$rootScope.showDash = true;
}
$rootScope.hasSubMenu = function(menuType){
if(menuType=='dashboard'){
$rootScope.showCC = false;
$rootScope.showDash = $rootScope.showDash === false ? true: false;
}
else if(menuType=='customerCare'){
$rootScope.showDash = false;
$rootScope.showCC = $rootScope.showCC === false ? true: false;
}
}
By default $rootScope.showDash and $rootScope.showCC are set to false. It will set the menus to closed when page is initially loaded. If you have more than two submenus add accordingly.
hasSubMenu() function will work for toggling between the menus. I have added a small condition
if(location[1] == 'customerCare'){
$rootScope.showCC = true;
}
else if(location[1]=='dashboard'){
$rootScope.showDash = true;
}
it will remain the submenu open after reloading the page according to selected menu item.
I have defined my pages like:
$routeProvider
.when('/dasboard/loan', {
controller: 'LoanController',
templateUrl: './views/loan/view.html',
controllerAs: 'vm'
})
You can use isActive() function only if you have a single menu without submenu.
You can modify the code according to your requirement.
Hope this will help. Have a great day :)

How to force update view from directive event in Angularjs

I have a work and stuck it 2 days. Hope everyone know angularjs help me :).
I need to force a change html when have a change on model. Example:
This is html code:
<!--CAKE LIST-->
<div id="cakelist" ng-controller="CakeListCtrl">
<ul class="thumbnails cake-rack" cakes="cakes" ng-model="cakesModel">
<li class="pull-left cake-unit" ng-repeat="cake in cakes" cake="cake">
<div class="thumbnail">
<a href="{{cake.link}}">
<img ng-src="{{cake.avatar}}" alt="{{cake.title}}" class="img img-rounded img-polaroid" />
</a>
<h5 class="pull-left">
{{cake.title}}
</h5>
Shared
<div class="clearfix"></div>
<ul class="attrs unstyled">
<li>
<div class="pull-left">Mã sản phẩm</div>
<span class="pull-right">{{cake.type}}</span>
</li>
</ul>
</div>
</li>
</ul>
<input type="button" class="btn btn-primary" value="add more cake" class="cake-more" ng-click="addCake()" />
<input type="button" class="btn btn-danger" value="clear cake" class="cake-clear" ng-click="clear()" />
<img alt="Loading" src="/imagesroot/ajax-loader-1.gif" loading-stage="loadingStage" class="cake-loading"/>
</div>
now a have a menu outside of controller:
<div id="cake-catalog" class="cake-catalog">
<ul class="nav">
<li class="active">
<a cake-menu-unit href="sacmscategory50c2302b7ff0a">Nhân vật hoạt hình</a>
</li>
<li>
<a cake-menu-unit href="sacmscategory50c2308717a84">Động vật</a>
</li>
<li>
<a cake-menu-unit href="sacmscategory50c2309da00f6">Tạo hình 3D</a>
</li>
<li>
<a cake-menu-unit href="sacmscategory50c230ba08d9d">Các mẫu hình khác</a>
</li>
</ul>
</div>
I have angular module for add and clear:
var CakeList = angular.module('CakeList', ['ngResource']);
CakeList.service('CakeService', function($rootScope) {
var cakedata = [{avatar:"test", title: "test2"}];
$rootScope.loadCake = false;
var bf = function() { $rootScope.loadCake=true; };
var at = function() { $rootScope.loadCake=false; };
return {
cakes: function() {
bf();
at();
return cakedata;
},
addCake: function() {
bf();
cakedata.push(cake);
at();
},
clear: function() {
cakedata = []; console.log('clear');
}
};
});
CakeList.directive('cakeCatalog', function($rootScope, CakeService) {
var clickfn = function(e) {
e.preventDefault();
CakeService.clear();
};
var nonclickfn = function(e) {
e.preventDefault();
console.log('nonclickfn');
};
return {
restrict: "C",
link: function(scope, element, attrs) {
$rootScope.$watch('loadCake', function(newValue, oldValue) {
if (newValue===true) {
element.find('a').off('click').on('click', nonclickfn);
}
else {
element.find('a').off('click').on('click', clickfn);
}
});
}
};
But when runtime, i put click on a element of menu then the list cake not clear, even i check console.log in console box and see the cakedata really clear!. Can you help me this case ? :)
First of all, the design seems a bit weird by using everywhere $rootScope (among other things). But that's not the cause of the problem. The problem is the $watch which is not correct.
First of all, use loadCake as an object instead of a primitive type:
var loadCake = { loaded: false};
Use the objectEquality parameter in your $watch statement:
$rootScope.$watch('loadCake', function(newValue, oldValue) {
if (!newValue) return;
if (newValue.loaded === true) {
element.find('a').off('click').on('click', nonclickfn);
}
else {
element.find('a').off('click').on('click', clickfn);
}
}, true);

Categories