How to navigate from tab to different Page and viceversa in angularJS? - angularjs

If i am having One page with 2 tabs. and if from 2nd tab i am navigating to different page. then how to come back to that 2nd tab from navigated page? i am using $StateProvider.
Thanks.

Here is the example code and it works well,
index.html
----------------
<html>
<head>
<title>Tabs Directive</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-rc.0/angular.min.js"></script>
<script src="tabController.js"></script>
</head>
<body>
<div class="container">
<section ng-app="myApp" ng-controller="TabController as tab">
<ul class="nav nav-pills">
<li ng-class="{active:tab.isSet(1)}"><a href ng-click="tab.setTab(1)">Tab 1</a></li>
<li ng-class="{active:tab.isSet(2)}"><a href ng-click="tab.setTab(2)">Tab 2</a></li>
<li ng-class="{active:tab.isSet(3)}"><a href ng-click="tab.setTab(3)">Tab 3</a></li>
</ul>
<div ng-show="tab.isSet(1)">
<h4>Tab 1</h4>
</div>
<div ng-show="tab.isSet(2)">
<h4>Tab 2</h4>
</div>
<div ng-show="tab.isSet(3)">
<h4>Tab 3</h4>
</div>
</section>
</div>
</body>
</html>
tabController.js
----------------
var app = angular.module('myApp', []);
app.controller('TabController', function () {
this.tab = 1;
this.setTab = function (tabId) {
this.tab = tabId;
};
this.isSet = function (tabId) {
return this.tab === tabId;
};
});

Thanks Atul :)
but this solution worked for me.
we can have one flag varibale ilke "this.isPageVisited=false" in APPCONTEXT.js file. so that variable will be available throughout the project. so suppose from tab of one page i am going to different page, what i do is i set isPageVisited=true via setter method in visted page . so now to come back to tab page again, we check the variable if its true or not. if it is true we put the "active" class to the tab element.
so that the we can have current tab active from where navigation started.

Related

Dropdown with delete options inside ng-repeat

How do I implement delete on click of a tag? When I delete click something, the view is not reflected until I do refresh.
<div class="dropdown">
<span ng-repeat="tag in tag track by $index" data-toggle="dropdown">[[tag]]</span>
<!--<a data-toggle="dropdown" href="#">Dropdown trigger</a>-->
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<li ng-click="deleteHashtag(p_id, tag, $index)" class="cursor">Delete</li>
<li class="divider"></li>
<li ng-click="showHashtags(tag)" class="cursor">View All</li>
</ul>
</div>
Below is the Angular code
$scope.deleteHashtag = function(p_id,hashtag, index){
$http.get("/api/hashtag/delete?contactId="+p_id.toString()+"&hashtag="+hashtag.toString())
.success(function(response){
console.log(response);
if(response.SuccessCode){
console.log("Deleted Tag");
}
else {
console.log("Delete fail");
}
});
$scope.hashtag.splice(index, 1);
};
Try putting the ng-repeat attribute inside the dropdown div. That way you will get a separate dropdown for each tag. You may need to turn the dropdown div into a span for it to look the same.
I wrote a little demo page that seems to do what you want. Click on each tag to bring up its own dropdown menu, then click delete and watch it go away. The demo code is below, and also lives in plunker here.
Some things to watch out for if you copy/paste:
The array of tags is called tags in my code. It was referred to as tag in your html and hashtag in your javascript.
I used $parent to access the dummy p_id variable since it's now being accessed from within the ng-repeat.
Good Luck!
<!doctype html>
<html ng-app="myApp">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<script>
angular.module('myApp', [])
.controller('MyController', ['$scope', function($scope) {
$scope.tags = ['javascript', 'webgl', 'angularjs', 'twitter-bootstrap', 'jquery'];
$scope.p_id = 'some value';
$scope.deleteHashtag = function(p_id, hashtag, index) {
// I removed the api call here since I don't have access to it and
// it doesn't seem to be part of the problem. You may want to put
// the splice inside the success method instead of outside though.
console.log('delete hash tag ' + p_id + ' ' + hashtag + ' ' + index);
$scope.tags.splice(index, 1);
};
$scope.showHashtags = function(tag) {
console.log('show hash tags');
// some function that does something not related to the problem at hand.
};
}]);
</script>
<style>
.spacey { margin-left: 3px; margin-right: 3px;}
.cursor { cursor: pointer; }
</style>
</head>
<body>
<div ng-controller="MyController as ctrl">
<span class="dropdown cursor" ng-repeat="tag in tags track by $index">
<span class="label label-default spacey" data-toggle="dropdown">{{tag}}</span>
<ul class="dropdown-menu">
<li ng-click="deleteHashtag($parent.p_id, tag, $index)" class="cursor">Delete</li>
<li class="divider"></li>
<li ng-click="showHashtags(tag)" class="cursor">View All</li>
</ul>
</span>
</div>
</body>
</html>
Try this.tag
<li ng-click="deleteHashtag(p_id, this.tag, $index)" class="cursor">Delete</li>
In case its not working, please post ur angular code as well
Your <li ng-click="deleteHashtag(p_id, tag, $index)" class="cursor">Delete</li> element is outside ng-repeat, so you pass to the deleteHashtag function full tag list. ng-repeat repeats the element where it is inserted and every child element.

Angularjs Div Show, Hide Toggle with adding class to active button

I'm new to this please bear with me
I'm trying to achieve div toggle and button class added when button clicked (active), i looked every where i been trying to do this for over 6 hours now :(.
here is my NAV div
<div id="sidebar-wrapper-button" ng-controller="Main">
<ul class="nav nav-pills">
<li ng-click="isInfo = !isInfo" ng-class="{'active':isInfo}"></li>
<li ng-click="isSetting = !isSetting" ng-class="{'active':isSetting}"></li>
</ul>
</div>
Content Div
<div ng-class="{'ng-show':isSetting,'ng-hide':!isSetting,'ng-hide':isInfo,}">
<h1>Setting</h1>
</div>
<div ng-class="{'ng-show':isInfo,'ng-hide':!isInfo,'ng-hide':isSetting}">
<h1>Info</h1>
</div>
app.js
//toggle Setting
app.controller('Main', function($scope) {
$scope.isSetting = false;
});
//toggle Info
app.controller('Main', function($scope) {
$scope.isInfo = false;
});
Thank you.
If I understood your request right, here's what I would do:
var app = angular.module('myApp', []);
app.controller('Main', function($scope) {
$scope.tabActive = null; // here insert 1, 2 or null depending on what the initial selection should be
});
li a{text-decoration: none;}
<link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-app="myApp">
<div ng-controller="Main">
<ul class="nav nav-pills">
<li ng-click="tabActive = 1" ng-class="{'active':tabActive == 1}">
</li>
<li ng-click="tabActive = 2" ng-class="{'active':tabActive == 2}">
</li>
</ul>
<div ng-show="tabActive == 1">
<h1>Info</h1>
</div>
<div ng-show="tabActive == 2">
<h1>Setting</h1>
</div>
</div>
</div>
Simpler way is to use angular expression {{}} to output appropriate string:
<h1>{{isSetting ? 'Setting' : 'Info'}}</h1>
Requires less markup and less class change logic code and ultimately less scope watches

How to refresh the previous page using AngularJS?

We have ASP.NET application where we use AngularJS. There's a page with the table (list) that contains pictures and their properties. The pictures are in first column of the table. The code looks as following:
<td>
<a ng-href="{{pic.FullUrl}}" target="_blank">
<img class="img-thumbnail" ng-src="{{pic.FullUrl}}" alt="{{pic.AltText}}" />
</a>
</td>
We can edit some picture by clicking "Edit" button and go to the next page (edit). After we made the changes, we click "Back" button to return to the previous page (list).
The issue is the image on first page hasn't been refreshed if we changed it on edit page, that is pic.FullUrl doesn't take effect.
I've tried to use the watch function, but no luck.
How to make it work?
UPDATE
We have a service:
PictureApp.factory('PictureService', function ($http, $location) {
var PictureService = function () {
this.ToList = function (objType, objId, mode) {
$location.path('/' + objType + '/' + objId + '/' + mode);
};
And we use it when accept changes on edit page in this way:
$scope.Accept = function () {
...
query.then(function () {
PictureService.ToList($routeParams.objType, $routeParams.objId, $routeParams.mode);
});
};
As you can see we call ToList and go to list page, but without reloading.
In list's controller we have this:
$scope.$watch('rbMode', function (val) {
PictureService.ToList($routeParams.objType, $routeParams.objId, val);
});
On list page we have this:
<div ng-if="dataLoaded">
<div ng-switch="rbMode">
<div ng-switch-when="static">
<div ng-include="'partials/Pic/PicTable.htm'" onload="this.pics = data;"></div>
</div>
<div ng-switch-when="banner">
<accordion close-others="false">
<accordion-group is-open="expandBanners" heading="{{pics[0].TypeDescription}}" ng-repeat="pics in data">
<div ng-include="'partials/Pic/PicTable.htm'" onload="this.pics = $parent.pics;" ></div>
</accordion-group>
</accordion>
</div>
</div>
</div>
And PicTable.htm looks as following:
<tr ng-repeat="pic in pics" ng-class="{'movable-row':isBanner}">
<td>{{pic.PictureLinkID}}</td>
<td>
<a ng-href="{{pic.FullUrl}}" target="_blank">
<img class="img-thumbnail" ng-src="{{pic.FullUrl}}" alt="{{pic.AltText}}" tooltip-popup-delay='1000' tooltip-placement="right" tooltip="Кликните, чтобы открыть в полном размере" />
</a>
</td>
Sounds like you have an image cache issue. Place a timestamp parameter on the end of your image url "*.jpg?ts=3324324". This will let the browser know it needs to refetch the image once it has been edited. Initialize the timestamp when the page loads and update the timestamp whenever an image is edited.
You can try the plnkr below which you can observe in your network panel, will fetch the image each time the timestamp is updated.
Edit: updated to demonstrate communication across controllers.
http://plnkr.co/edit/lp9lwkR3hgsqtIt4c3N0?p=preview
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-rc.1" src="https://code.angularjs.org/1.4.0-rc.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div ng-controller="cntrl">
<img ng-src="{{imgurl}}'?ts={{lastEdit}}" />
</div>
<div ng-controller="editCntrl">
<button ng-click="updateTS()">Update ts</button>
</div>
<script>
var app = angular.module("app",[]);
app.controller("cntrl",function($scope){
$scope.lastEdit = (new Date()).getTime();
$scope.imgurl = "http://dummyimage.com/600x400/000/fff";
$scope.$on("edited",function(){
$scope.lastEdit = (new Date()).getTime();
});
});
app.controller("editCntrl",function($scope,$rootScope){
$scope.updateTS = function(){
$rootScope.$broadcast("edited");
}
});
angular.bootstrap(document,["app"]);
</script>
</body>
</html>
You can add time stamp to uniquely identify image url on change.
on edit add the time stamp like this...
pic.FullUrl = "...path/pic.jpg"+ "?ts=" +new Date();
this will tell the browser that your image had been changed and it will do refresh.

AngularJs hide div elements for specific path/controllers

I have the following structure:
<html>
<head>
// additional info here
</head>
<body data-ng-app="myApp" data-ng-controller="contentController">
<div id="container">
<div id="id1">
//content here
</div>
<div id="id2">
//content here
</div>
<div id="id3">
//content here
</div>
<div id="page-content">
<div data-ng-view="">
//here will be loaded the other views
//Example: /profile, /login, /register, etc etc)
</div>
</div>
</div>
</body>
</html>
What I need is to hide the divs: id1, id2, id3 when the user navigates to specific pages like /login or register. For all other pages the divs: id1, id2, id3 should be visible.
At the moment when the user navigates to /login the divs: id1, id2, id3 content is shown with the login form so I have to hide it somehow.
The divs: id1, id2, id3 are common for all pages except for /login, /register and /forgot.
You can use the $locationChangeSuccess event broadcasted from the $rootScope to check the current route using the $route service. The advantage of this methodology, is that navigation through the use of the address bar can still be detected.
DEMO
JAVASCRIPT
.controller('contentController', function($scope, $rootScope, $route) {
var paths = ['/login', '/register', '/forgot'];
$rootScope.$on('$locationChangeSuccess', function() {
var $$route = $route.current.$$route;
$scope.contentVisibility = $$route && paths.indexOf($$route.originalPath) < 0;
});
});
HTML
<body data-ng-app="myApp" data-ng-controller="contentController">
<div id="container">
<div id="id1" ng-show="contentVisibility">
//content here
</div>
<div id="id2" ng-show="contentVisibility">
//content here
</div>
<div id="id3" ng-show="contentVisibility">
//content here
</div>
<div id="page-content">
<div data-ng-view="">
//here will be loaded the other views
//Example: /profile, /login, /register, etc etc)
</div>
</div>
<!-- list of routes bound within the anchor tags -->
<a ng-repeat="path in [
'/login', '/register', '/forgot',
'/other-route-1', '/other-route-2', '/other-route-3']"
ng-href="#{{path}}">{{path}}<br></a>
</div>
</body>
you should use data-ng-hide to hide your contents. however, you have to set the variable at start of your specific controller in order to hide the contents and in other controllers you should set it false to show the contents.
At the beginning of your specific controller:
var $scope.contentHide = true;
At the beginning of other controllers:
var $scope.contentHide = false;
<div id="id1" data-ng-hide="contentHide">
//content here
</div>
<div id="id2" data-ng-hide="contentHide">
//content here
</div>
<div id="id3" data-ng-hide="contentHide">
//content here
</div>

AngularJS - Create a dynamic, generic header

In my AngularJS application, I'm using a router with an ng-view directive.
Besides it I would like to add a generic header (same for all the views). So I did the following:
<!-- index.html -->
<body ng-app="myApp">
...
<div ng-controller="TopmenuCtrl" class="header">
<div ng-include="template.url"></div>
...
</div>
<div ng-view></div>
</body>
The view is dynamic depending on the session token:
<!-- views/topmenu.html -->
<ul class="nav nav-pills pull-right">
<li class="active"><a ng-href="#">Home</a></li>
<li><a ng-href="#">About</a></li>
<li><a ng-href="#">Contact</a></li>
<li ng-show="token"><a ng-href="#" ng-click="doLogout()">Logout</a></li>
</ul>
And the topmenu controller with the logout method:
// controllers/topmenu.js
$scope.template = {url: 'views/topmenu.html'};
$scope.doLogout = function() {
localStorageService.clearAll();
$window.sessionStorage.token = '';
$location.path('/login');
};
The problem is: When I click on "logout" in the app, the topmenu controller is called and destroy the session but the main one from the router is called too and display an error because the session was destroyed!
The only (not satisfactory) solution I found to prevent this is to add this code in each controllers of the app:
if ($window.sessionStorage.token = '') {
return;
}
Is there a way to execute the header controller but not the main ng-view controller?
I finally found my answer: https://stackoverflow.com/a/11672909/900416.
Now my logout link looks like: <a href ng-click="doLogout()">Logout</a>.

Resources