ng-class not evaluating to true - angularjs

I have some html with which I'm trying to use ng-class. If I just hardcode in "true", my CSS for the class is applied as expected. But, as soon as I replace the true with an expression (shown below), it seems my class isn't being applied. Here is the line of HTML:
<li ng-repeat="menuItem in menuItems"><span ng-class="{active: $index==activeIndex}" class="underline"><a ng-href={{menuItem.itemLink}}>{{menuItem.itemName}}</a></span></li>
And the code from the controller:
$scope.$on('$routeChangeSuccess', function(index){
$scope.activeIndex = index;
console.log("Set Active Index");
});

It seems the index param of the '$routeChangeSuccess' event callback is not a number as you expected.
If you want to change your actived list when route change. you can pass $location service to $scope.
here is example: http://jsfiddle.net/yRHwm/4/
HTML code:
<div ng-app="myapp">
<div class="container" ng-controller="MyCtrl">
<li ng-repeat="menuItem in menuItems">
<!-- use $location.path() to detect current path -->
<span ng-class="{'active': menuItem.itemLink==$location.path()}" class="underline">
<a ng-href="#{{menuItem.itemLink}}">{{menuItem.itemName}}</a>
</span>
</li>
</div>
<div ng-view></div>
</div>
Javscript Code:
angular.module('myapp', ['ngRoute'])
.config(function($routeProvider){
$routeProvider
.when('/1', {controller:'firstController'})
.when('/2', {controller:'secondController'})
})
.controller('MyCtrl', function($scope, $location) {
$scope.menuItems = [
{itemLink: '/1', itemName: 'Link1'},
{itemLink: '/2', itemName: 'Link2'}
];
// pass $location service to scope, then you can use $location.path() to detect current path
$scope.$location = $location;
// this is no longer used. just to show index is not a number
$scope.$on('$routeChangeSuccess', function(index){
$scope.activeIndex = index;
// you can see in the console which index is not a number.
console.log("Set Active Index", index);
});
})
.controller('firstController', function($scope){
console.log('first');
})
.controller('secondController', function($scope){
console.log('second');
});

Related

Scope doesn't work

I'd like to set a scope for a different route but it seems not working...
var app = angular.module('AngularApp', ['ngRoute', 'ngAnimate']);
app.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'menu.html',
controller: 'MenuController'
}).when('/slides/:menuItem', {
templateUrl: 'slides.html',
controller: 'SlidesController'
});
});
app.controller('MenuController', function($scope, $http) {
$http.get('database.json').then(function(response) {
$scope.bottomBar = 'no';
$scope.pageClass = 'menus';
$scope.database = response.data;
});
});
app.controller('SlidesController', function($scope, $http, $routeParams) {
$http.get('database.json').then(function(response) {
$scope.bottomBar = 'yes';
$scope.pageClass = 'slides';
$scope.database = _.find(response.data.menuItems, {'url': $routeParams.menuItem});
});
});
<body ng-app="AngularApp">
<div class="line">
<div class="col-12">
<img src="images/logo.jpg">
</div>
</div>
<div class="page {{pageClass}}" ng-view></div>
<div class="bottom-bar">
<ul>
<li>Retour {{bottomBar}}</li>
</ul>
</div>
</body>
bottomBar is empty...
Looks like you are putting html in app directly.
You can move below code in a template and use ng-include to add this template in you all views.
<div class="bottom-bar">
<ul>
<li>Retour {{bottomBar}}</li>
</ul>
</div>
This is because your controller scope is present in this div with ngView. Therefore anything outside this div won't have scope binding.
<div class="page {{pageClass}}" ng-view></div> <!-- controller active here only -->

How to append the new content in angulularJS template in ng -repeat without destroying previous content

How to append the new content in angulularJS template in ng -repeat without destroying previous content
1.I want to dispaly the myvar data in every save click
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyController', ['$scope', '$http', function ($scope, $http, $filter, $rootScope) {
$scope.view= function () {
//some ajax calll
$scope.myvar = data;
};
}]);
</script>
</head>
<body ng-app="myApp" ng-controller="MyController">
<ul>
<li class="Status" ng-repeat="item in myvar">
{{item.var}}
</li>
</ul>
<button ng-click="view()">View More</button>
2.I please suggest me
According to ng-repead documentation (check Tracking and Duplicates section) "track by $index" is what you need
<li class="Status" ng-repeat="item in myvar track by $index">
{{item.var}}
</li>
You can also use "track by yuor_primary_key".
You need to push new element every time in array
Check this code: http://codepen.io/anon/pen/bEwBwQ
Controller
angular.module('DemoApp', ['ui.router', 'ngAnimate'])
.controller('DemoController', function($scope, $window, $state) {
$scope.myvar = [{"var" : 1}];
$scope.save = function() {
//some ajax calll
var v = {"var" : 1};
$scope.myvar.push(v);
};
});
HTML
<ul>
<li class="Status" ng-repeat="item in myvar">
{{item.var}}
</li>
</ul>
<button ng-click="save()">save</button>

Implementing angularJs factory or service for bootstrap tabs

how to write a service or factory for bootstrap tabs using angularJs.
I placed in one controller but need a common function(repeated code) for different controllers.
<ul class="nav nav-tabs">
<li data-ng-class="{active:tab===0}">
<a href ng-click="changeTab(0)"> <i class="fa fa-list"></i></a>
</li>
<li data-ng-class="{active:tab===1}">
<a href ng-click="changeTab(1)"><i class="fa fa-user"></i></a>
</li>
</ul>
<div data-ng-class="{activeTab:tab===0}" ng-show="isActiveTab(0)">
tab1
</div>
<div data-ng-class="{activeTab:tab===1}" ng-show="isActiveTab(1)">
tab2
</div>
controller
$scope.tab = 0;
$scope.changeTab = function(newTab){
$scope.tab = newTab;
};
$scope.isActiveTab = function(tab){
return $scope.tab === tab;
};
Managing tabs is a view concern. Rather than implementing a factory, I recommend creating two directives: tabContainer and tab. The tab directive registers itself with the parent tabContainer using the require attribute to access the parent directive's controller API.
Demo
Usage
<tab-container selected="tab2">
<tab name="tab1">tab1</tab>
<tab name="tab2">tab2</tab>
</tab-container>
Parent Directive
The parent directive publishes the following controller API that the child tab directives will access:
tabContainer controller
// registers this tab with the parent tabContainer
this.register = function(element) {
$scope.tabs.push(element);
}
// returns the selected tab object whose
// name property indicates which tab is active
this.getSelected = function() {
return $scope.selectedTab;
}
Child Directive
The tab directive is able to access the parent controller by requiring the parent directive in its directive definition, and accessing the parent directive's controller as the 4th argument to the tab directive's link function:
tab directive definition
scope: true,
require: '^tabContainer',
link: function(scope, element, attr, tabContainer) {
// set the tab so that it is visible in the tab directive's scope.
scope.tab = { name: attr.name, element:element};
scope.selectedTab = tabContainer.getSelected();
tabContainer.register(scope.tab);
}
The scope is set to true so that each tab will create its own child scope and not interfere with the scope of other tabs.
Template Files
For example purposes, the directive templates are embedded in the HTML:
<script type="text/ng-template" id="tabContainer.html">
<ul class="nav nav-tabs">
<li ng-repeat="tab in tabs" data-ng-class="{active:selectedTab.name===tab.name}">
<a href ng-click="changeTab(tab)"> <i class="fa fa-list">{{tab.name}}</i></a>
</li>
</ul>
<ng-transclude></ng-transclude>
</script>
<script type="text/ng-template" id="tab.html">
<div data-ng-class="{activeTab:selectedTab.name===tab.name}" ng-show="selectedTab.name === tab.name">
<ng-transclude></ng-transclude>
</div>
</script>
It is recommended to move these to dedicated HTML files.
Changing the Active Tab
The user is able to change the active tab by clicking the tab link. This is achieved by publishing a $scope function in the parent controller:
$scope.changeTab = function(tab) {
$scope.selectedTab.name = tab.name;
}
Creating a Tabs Module
The beauty of AngularJS and its pluggable modular architecture is that you can extend the AngularJS directive ecosystem, and have the directives work together seamlessly. For example, you could encapsulate the above tabs directive into a tabs module, and even use the ngRepeat directive to bind the tabs.
Demo
Controller
var app = angular.module('app',['tabs']);
app.controller('ctrl', function($scope) {
$scope.tabData = [
{ name: 'tab1', body: 'You selected tab1!'},
{ name: 'tab2', body: 'You selected tab2!'},
{ name: 'tab3', body: 'You selected tab3!'},
{ name: 'tab4', body: 'You selected tab4!'},
];
});
View
<div class="container" ng-controller="ctrl">
<tab-container selected="tab1">
<tab ng-repeat="tab in tabData" name="{{tab.name}}">{{ tab.body }} </tab>
</tab-container>
</div>
Hi I write it with out using any service or factory
see the example
<ul ng-init="tab = 1">
<li ng-class="{active:tab===1}">
<a href ng-click="tab = 1">Tab1</a>
</li>
<li ng-class="{active:tab===2}">
<a href ng-click="tab = 2">Tab2</a>
</li>
<li ng-class="{active:tab===3}">
<a href ng-click="tab = 3">Tab3</a>
</li>
<br><br>
<p ng-show="tab === 1"> Tab1 content </p>
<p ng-show="tab === 2"> Tab2 content</p>
<p ng-show="tab === 3"> Tab3 content</p>
</ul>
Dynamically change it through controller see the working example here
The structure for controllers/services in Angular are explained well here:
https://github.com/johnpapa/angular-styleguide
In app.js, we declare an angular application, give it a name, and any dependencies (ng-route / ng-grid). $http calls should be made using a factory or a service, and the controller should call the service to fetch or post data. From the angular documentation, "services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app."
https://docs.angularjs.org/guide/services
app.js:
var app = angular.module('appname', []);
app.factory('httpResponseErrorInterceptor'...
app.config(['$httpProvider',...
Controller:
angular.module('appname').controller("NameCtrl", ["$scope", "$log", "$window", "$http", "$timeout", "SomeService",
function ($scope, $log, $window, $http, $timeout, TabService) {
//your controller code
$scope.tab = 0;
$scope.changeTab = function(newTab){
$scope.tab = newTab;
};
$scope.isActiveTab = function(tab){
return $scope.tab === tab;
};
}
]);
Service:
angular.module('appname').service("TabService", function () {
//Your code for shared functionality regarding tab service
var currentTab = {};
return {
currentTab : currentTab
}
});

template not displaying binded data after routed, on first click - AngularJS

Trying to route to different view template from the index page. Initially, the list on main index page gets loaded and the main.html gets loaded in ng-view, displaying it's text contents. The data from 'MainCtrl' is broadcasted properly and works fine. Now, the confusion is, when the item from the list is clicked, it gets routed to content template(content.html), but the content does not display the binded value on the first click on the list. But, after second click, it starts showing the binded values that is broadcasted from MainCtrl.
<body ng-app="myApp">
<div ng-controller="MainCtrl">
<ul ng-repeat="value in msg" ng-click="setSelectedValue(value)">
<li>
<a href='#/content'>{{ value }}</a>
</li>
</ul>
</div>
<div ng-view=""></div>
main.html:
<p>Select from the list.</p>
content.html:
//loads the selected item from the list on index page
<h3>Selected: {{ message }}</h3>
angular
.module('myApp', ['ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/content', {
controller: 'ContentCtrl',
templateUrl: 'views/content.html'
})
.otherwise({
redirectTo: '/'
});
})
.factory('myService', function($http, $rootScope){
var sharedService ={};
sharedService.message = '';
sharedService.prepforBroadcast = function(value){
this.message = value;
this.broadcastItem();
};
sharedService.broadcastItem = function(){
$rootScope.$broadcast ('handleBroadcast');
};
return {
sharedService: sharedService
};
})
.controller('MainCtrl', function ($scope, myService) {
$scope.msg = data; //this will be json data
$scope.selectedValue;
$scope.setSelectedValue = function(value){
$scope.selectedValue = value;
myService.sharedService.prepforBroadcast(value);
}
})
.controller('ContentCtrl', function ($scope, myService) {
$scope.$on('handleBroadcast', function(){
$scope.message = myService.sharedService.message;
})
});
Not sure what exactly is the reason for not binding the data on the very first click even though when the template loads instantly. Any help or thought would be greatly appreciated. Scratching my head for a while.
<ul ng-repeat="value in msg" ng-click="setSelectedValue(value)">
check with out ng-click="setSelectedValue(value)" part. seems like ur click is going to handle by setSelectedValue(value) function
The ng-repeat and ng-click should be on li.
<ul>
<li ng-repeat="value in msg" ng-click="setSelectedValue(value)">
<a href='#/content'>{{ value }}</a>
</li>
</ul>

AngularJS $location.path() changed after upgrading to 1.1.15

I have a NavigationController that has a selectedItem for the current selected item in a navigation list. It uses $location.path() to try and set it to a default value. It's in hashbang mode. Here is a simplified version:
App.controller("NavigationController", ['$scope', '$location', function($scope, $location) {
$scope.currentSelection = $location.path() || "/dashboard";
$scope.select = function( name ) {
$scope.currentSelection = name;
}
}]);
And the html:
<body ng-app="App">
<div class="container-fluid absoluteFill">
<div class="row-fluid fill" ng-controller="NavigationController">
<div class="span2 nav-bubble fill">
<ul class="nav nav-list">
<li>Option 1</li>
<li>Option 2</li>
<li>Option 3</li>
</ul>
</div>
<div ng-view></div>
</div>
</div>
</body>
And the config:
angular.module("App", ["ngResource"])
.config(function($routeProvider) {
$routeProvider.
when( '/', { redirectTo: '/dashboard' }).
when( '/dashboard', {
controller: 'DashboardController',
templateUrl: '/gpa/app/views/dashboard.html'
}).
otherwise({redirectTo: '/'});
})
The problem is that when I navigate to /home/index (without a hash bang) $location.path() returns "/index" where it used to return null prior to 1.1.15. However, if I go to "/home/index#/dashboard it returns "/dashboard" as expected. I tried redirecting when someone goes to "/" to "/dashboard", but NavigationController is called prior to being redirected so it continues to get "/index".
So how can I at least tell when the hashbang is not included? $location.hash() always seems to return "". I don't want to hard code "/index" in my code to know when nothing is on the URL.
I think you want to use the $route service and hook into the $routeChangeSuccess event.
App.controller("NavigationController", function($scope, $location) {
$scope.$on("$routeChangeSuccess", function (scope, next, current) {
$scope.currentSelection = $location.path() || "/dashboard";
});
$scope.select = function( name ) {
$scope.currentSelection = name;
}
});

Resources