AngularJS: how do I get the hash value within the URL - angularjs

AngularJS noob here.
I want my application to be able to respond to a url hash. By respond I mean simple stuff like set a variable value.
In this example, if the url is http:example.com/#parents-to-be, I want the app to perform the standard behaviour which is scroll to #parents-to-be, and also set $scope.tab3 = 1;
From doing some research, it seems like this can be achieved with a combination of $location.hash() and $anchorScroll(). However, I haven't been successful thus far. Can someone please help?
html:
<div ng-app="bug">
<div ng-controller="TabsController">
<a href ng-click="activateTab(1)">tab 1</a>
<a href ng-click="activateTab(2)">tab 2</a>
<a href ng-click="activateTab(3)">tab 3</a>
<div id="parents-to-be"> <!-- this is the target div -->
<div ng-show="tab1 === 1">content of tab 1</div>
<div ng-show="tab2 === 1">content of tab 2</div>
<div ng-show="tab3 === 1">content of tab 3</div>
</div>
</div> <!-- /angular tabs controller scope -->
</div> <!-- /angular app scope -->
app.js:
(function() {
var app = angular.module('bug', []);
app.controller('TabsController', function($scope, $location, $anchorScroll) {
// init tabs
$scope.initTabs = function() {
$scope.tab1 = 0;
$scope.tab2 = 0;
$scope.tab3 = 0;
};
// activate tabs
$scope.activateTab = function(tab_index) {
$scope.initTabs();
$scope['tab' + tab_index] = 1;
};
// this is the part of the app where I try to get the hash value and edit the value of tab3
$scope.hash_value = $location.hash();
if ($scope.hash_value === "parents-to-be") {
$scope.activateTab(3);
$anchorScroll();
}
});
})();
Thank you!

Use the $on event handler to capture the hash value after the $locationChangeSuccess event:
$rootScope.$on('$locationChangeSuccess', function()
{
console.log(arguments[1].replace(/[^#]+(#.+)/, "$1") );
}
)
angular.element(document).injector().get('$rootScope').$on('$locationChangeSuccess', function(){console.log(arguments[1].replace(/[^#]+(#.+)/, "$1"))})
References
feat($location): add support for History API state handling
hashchange Event Reference

Related

How to get attribute value of of the immediate parent of a clicked element

I am trying to get attribute value of the immediate parent of a clicked anchor. Any ideas on how I can achieve this. My code looks like below:
HTML
<div class="perTalk" catch="1">
<div>Content one</div>
Reply
</div>
<div class="perTalk" catch="1.1">
<div>Content two</div>
Reply
</div>
<div class="perTalk" catch="1.2">
<div>Content three</div>
Reply
</div>
AngularJS
var app = angular.module('myApp', []);
app.controller('../scripts/sleek-angular-control', function ($scope) {
$scope.idVal = function () {
var catchVal = $(this).closest(".perTalk").attr("catch");
$scope.firstname = catchVal;
$scope.lastname = "Doe";
}
});

AngularJS page navigation

What approach do you recommend to navigate pages from nav menu using angularjs?
Pages will have footer and header html using ng-include to have common templates. I found ng-view to navigate between pages.
In this example, there's a module named navList and a controller and a method navClass inside it. Using a special service in angular.js, $location which parses the URL in the browser and makes the URL available in the application. Finally, just match the URL hash with the parameter passed.
var navList = angular.module('navList', []);
navList.controller('navCtrl', ['$scope', '$location', function ($scope, $location) {
$scope.navClass = function (page) {
var currentRoute = $location.path().substring(1) || 'home';
return page === currentRoute ? 'active' : '';
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="well sidebar-nav" ng-app="navList">
<ul class="nav nav-list" ng-controller="navCtrl">
<li ng-class="navClass('home')"><a href='#/home'>Home</a></li>
<li ng-class="navClass('about')"><a href='#/about'>About Us</a></li>
<li ng-class="navClass('contact')"><a href='#/contact'>Contact Us</a></li>
</ul>
</div>
JsFiddle Link
Angular router is what you need:
https://github.com/angular-ui/ui-router/blob/master/README.md

How to use $event only for parent element in Angular JS?

I have HTML code with ng-click event:
<div class="btn share" ng-click="do($event)">
<span">1</span>
</div>
Angular JS:
$scope.do = function (event) {
var target = angular.element(event.target);
var parsed = parseInt(target.find('span').text(), 10);
}
When I click to element div or child element span is called event do().
But if I click on span my counter inside span is not increment. Only by clicking parent element div.
How I can set same $event for div and span elements?
I would recommend to work with scope bindings instead of DOM textContent:
<div class="btn share" ng-click="do()">
<span>{{count}}</span>
</div>
and in controller
$scope.count = 0;
$scope.do = function () {
$scope.count++;
};
If you however still want to know why it failed with your approach, it's because you need to use currentTarget, not just target:
angular.module('demo', []).controller('MainCtrl', function($scope) {
$scope.do = function(event) {
var target = angular.element(event.currentTarget);
var parsed = parseInt(target.find('span').text(), 10);
target.find('span').text(parsed + 1);
};
});
<script src="https://code.angularjs.org/1.4.3/angular.js"></script>
<div ng-app="demo" ng-controller="MainCtrl" class="btn share" ng-click="do($event)">
<span>1</span>
</div>
But don't do this, controller should not work with DOM at all, this is
not what controllers are for.
You're doing it the wrong way. Angular is not jQuery. You shouldn't do any DOM manipulation in the controller. The view should be generated based on the model, and not vice-versa.
The code should be
<div class="btn share" ng-click="do()">
<span>{{ counter }}</span>
</div>
and in the controller:
$scope.counter = 1;
$scope.do = function() {
doSomethingWithCounter($scope.counter);
}
Have you tried adding the same click event to your span also?
Like this
<span ng-click="do($event)"> 1 </span>

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
}
});

AngularJS $scope variable on window onclick

I have a button which when clicked displays a windows and hides it when the button is clicked again.I want the window to close even if any other place in the page is clicked.
This is my code :
<a class="btn dropdown-toggle multiselect-btn" ng-click="content=!content;contentClick=true">
//The div to show hide
<div ng-class="{'open':content}" > div content </div>
I wrote the following window on click code in the controller but it didn't work..
$window.onclick = function () {
if($scope.contentClick){
$scope.contentClick=0;
}
else{$scope.content=false;
$scope.$apply();}
}
What is the correct way to do this?Can anyone please guide me in the right direction.Thanks.
Try this, change your controller ID:
window.onclick = function () {
var scope = angular.element(document.getElementById('controller_id')).scope();
if(scope.contentClick){
scope.contentClick=0;
}
else{
scope.content=false;
scope.$apply();
}
}
I'm not sure what do you want to achieve after content was clicked, but you can $watch content value in controller and run some action when content change value
Please see script below
var app = angular.module('app', []);
app.controller('fCtrl', function($scope) {
$scope.$watch('content', function(value) {
if (value) {
$scope.contentClick = 1;
} else {
$scope.contentClick = 0;
}
})
});
.open {
color: red ;opacity: 0.5;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="fCtrl">
<a class="btn dropdown-toggle multiselect-btn" ng-click="content=!content;contentClick=true">Click me </a>
<hr/>//The div to show hide
<div ng-class="{'open':content}">div content {{contentClick}}
</div>
</div>
</div>

Resources