angularjs show/hide tabs - angularjs

Here i am displaying tabs from array using angularjs and bootstrap.
What i want is when i click on particular tab it should display content of that tab only.
i.e(When i click on dynamic-2 i want to display content of dynamic 2 and hide the content of dynamic-1 and dynamic-3 tab)
Right now i am getting content of all tabs on clicking.
js file
var items=[
{
Name:"tab1",
id:1,
content:"FirstTab",
title:"Dynamic-1",
templateUrl:"first.html"
},
{
Name:"tab2",
id:2,
content:"SecondTab",
title:"Dynamic-2",
templateUrl:"second.html"
},
{
Name:"tab3",
id:3,
content:"ThirdTab",
title:"Dynamic-3",
templateUrl:"third.html"
}
];
}]);
html file
<ul class="nav nav-tabs">
<li ng-repeat="l in list" >
<a href="#firsttab" ng-click="tab = 1" data-toggle="tab" >
{{l.title}} </a>
<div class="tab-content" >
<div id="firsttab" ng-click="tab = 1" ng-
show="tab===1">
Id: {{l.id}} <br>
Name: {{l.Name}} <br>
Content: {{l.content}} <br>
TemplateFile: <div ng-include="l.templateUrl"></div>
</div>
</ul>
</div>
</li>

model.js(Just change the code of this file with the code I have written below. It will give you desired result)
We have to provide delay to broadcast to make it work.
define(['jquery','ocLazyLoad','cssinjector'], function() {
var app=angular.module('App', ['angular.css.injector','oc.lazyLoad']);
app.controller('mycontroller', ['$scope','$ocLazyLoad','cssInjector','$rootScope','$timeout',
function($scope,$ocLazyLoad,cssInjector,$rootScope,$timeout) {
alert("modal-loaded");
$ocLazyLoad.load("http://localhost:8080/tabs/js/modal1.js")
.then(function(){
alert("modal1 loaded");
$scope.view="http://localhost:8080/tabs/view.html";
cssInjector.add("http://localhost:8080/tabs/style.css");
});
// ARRAY
var items=[
{
Name:"tab1",
id:1
},
{
Name:"tab2",
id:2
},
{
Name:"tab3",
id:3
}
];
$timeout(function(){
$rootScope.$broadcast('itmObj', items);
},0);
}]);
angular.element(function() {
angular.bootstrap(document, ['App']);
});
});

If you broadcast like this in parent controller
$scope.$broadcast('itmObj',{ itemsArray: items});
Then you can use the on-catch in child controller like
and you eill have the items array in args.itemsArray
$scope.$on('itmObj', function (event, args) {
var x = args.itemsArray; // args.itemsArray is your items from parentcontroller
});

Trying to add a promise on lazyloading the modalController and modal view will look like this
Modal.js
define(['jquery','ocLazyLoad','cssinjector'], function() {
var app=angular.module('App', ['angular.css.injector','oc.lazyLoad']);
app.controller('mycontroller', ['$scope','$ocLazyLoad','cssInjector',
function($scope,$ocLazyLoad,cssInjector) {
alert("modal-loaded");
// ARRAY
var items=[{
Name:"tab1",
id:1
},{
Name:"tab2",
id:2
},{
Name:"tab3",
id:3
}];
var lazyLoadModal1 = function(){
var deferred = $q.defer();
$ocLazyLoad.load("http://localhost:8080/tabs/js/modal1.js")
.then(function(){
alert("modal1 loaded");
$scope.view="http://localhost:8080/tabs/view.html";
cssInjector.add("http://localhost:8080/tabs/style.css");
deferred.resolve();
},function(){
deferred.reject();
});
return deferred.promise;
};
var init = (function(){
lazyLoadModal1().then(function(){
$scope.$broadcast('itmObj', {item:items});
});
})();
}]);
View.html
<div ng-controller="modalcontroller">
<div ng-repeat="vm in itemsArray">
<p>{{vm.Name}}</p>
<p>{{vm.id}}</p>
</div>
</div>
Modal1.js
angular.module('App', ['angular.css.injector','oc.lazyLoad'])
.controller("modalcontroller", ['$scope','$ocLazyLoad','cssInjector',
function($scope,$ocLazyLoad,cssInjector){
alert("In modal Controller");
$scope.$on("broadcast-started", function (event, data){
$scope.itemsArray=data.item;
console.log($scope.itemsArray);
});
}]);

Related

Binding expression in ng-repeat

I have the list of items
<ul>
<li><a>ItemA</a></li>
<li><a>ItemB{{vm.count}}</a></li>
</ul>
I am preparing the list in angular in Controller:
vm.listofItems =[{"textDisplay":"ItemA","Statego":""},
{"textDisplay":"ItemB{{vm.count}}","Statego":""}];
After some service call I'll get vm.count value? how to Bind now.
Ok just try this code, First of all i will suggest you to use $scope. I have assigned your listOfItems in watch of count, it will work for you, whenever you change the value of $scope.count
$scope.count;
$scope.$watch('count', function() {
$scope.listofItems =[
{"textDisplay":"ItemA","Statego":""},
{"textDisplay":"ItemB" +$scope.count,"Statego":""}
];
});
In Html
<div ng-app="app">
<div ng-controller="MainCtrl as main">
<ul>
<li ng-repeat='list in main.listofItems'>
{{list.textDisplay}}
</li>
</ul>
<input ng-model='main.count' ng-value='main.count'> {{main.count}}
</div>
</div>
In controller
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
var vm = this;
vm.count = 90;
vm.listofItems = [{
"textDisplay": "ItemA",
"Statego": ""
}, {
"textDisplay": "ItemB " + vm.count + "",
"Statego": ""
}];
$scope.$watch(angular.bind(this, function() {
return this.count;
}), function(newVal) {
vm.listofItems[1].textDisplay = "ItemB " + newVal;
// console.log(' change ' , newVal);
});
});
This the solution I figured out.Is this approach is correct?
jsFiddle for the same: https://jsfiddle.net/nj5/ve4xmhtj/

AngularJs requires page refresh after API call

I am writing an angularjs app. The requirement is to display the user's data once the user logs in. So when an user successfully logs in, he/she is routed to the next view. My application is working fine upto this point. Now as the next view loads I need to display the existing records of the user. However at this point I see a blank page, I can clearly see in the console that the data is being returned but it is not binding. I have used $scope.$watch, $scope.$apply, even tried to call scope on the UI element but they all result in digest already in progress. What should I do? The page loads if I do a refresh
(function () {
"use strict";
angular.module("app-newslist")
.controller("newsController", newsController);
function newsController($http,$q,newsService,$scope,$timeout)
{
var vm = this;
$scope.$watch(vm);
vm.news = [];
vm.GetTopNews = function () {
console.log("Inside GetTopNews");
newsService.GetNewsList().
then(function (response)
{
angular.copy(response.data, vm.news);
}, function () {
alert("COULD NOT RETRIEVE NEWS LIST");
});
};
var el = angular.element($('#HidNews'));
//el.$scope().$apply();
//el.scope().$apply();
var scpe = el.scope();
scpe.$apply(vm.GetTopNews());
//scpe.$apply();
}
})();
Thanks for reading
you don't show how you're binding this in your template.. I tried to recreate to give you a good idea.
I think the problem is the way you're handling your promise from your newsService. Try looking at $q Promises. vm.news is being updated by a function outside of angular. use $scope.$apply to force refresh.
the original fiddle is here and a working example here
(function() {
"use strict";
var app = angular.module("app-newslist", [])
.controller("newsController", newsController)
.service("newsService", newsService);
newsController.$inject = ['$http', 'newsService', '$scope']
newsService.$inject = ['$timeout']
angular.bootstrap(document, [app.name]);
function newsController($http, newsService, $scope) {
var vm = this;
vm.news = $scope.news = [];
vm.service = newsService;
console.warn(newsService)
vm.message = "Angular is Working!";
vm.GetTopNews = function() {
console.log("Inside GetTopNews");
newsService.GetNewsList().
then(function(response) {
$scope.$apply(function() {
$scope.news.length > 0 ? $scope.news.length = 0 : null;
response.data.forEach(function(n) {
$scope.news.push(n)
});
console.log("VM", vm);
})
}, function() {
alert("COULD NOT RETRIEVE NEWS LIST");
});
};
}
function newsService($timeout) {
return {
GetNewsList: function() {
return new Promise(function(res, rej) {
$timeout(function() {
console.log("Waited 2 seconds: Returning");
res({
data: ["This should do the trick!"]
});
}, 2000);
})
}
}
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.9/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.min.js"></script>
<body>
<div class="main">
<div class="body" ng-controller="newsController as vm">
Testing: {{ vm.message }}
<br>{{ vm.news }}
<br>{{ vm }}
<br>
<button class="getTopNewsBtn" ng-click="vm.GetTopNews()">Get News</button>
<br>
<ul class="getTopNews">
<li class="news-item" ng-repeat="news in vm.news track by $index">
{{ news | json }}
</li>
</ul>
</div>
</div>
</body>

AngularJs - RXJS Observable unsubscribe

I have setup an RXJS observable. I have two components which subscribe to a subject in service factory. How do I unsubscribe a selected component to the subject so that a button is pressed it stops listening to the subject broadcast?
See my jsfiddle Unsubscribe App
My code:
<div ng-app="myApp" ng-controller="mainCtrl">
<script type="text/ng-template" id="/boxa">
BoxA - Message Listener: </br>
<strong>{{boxA.msg}}</strong></br>
<md-button ng-click='boxA.unsubcribe()' class='md-warn'>Unsubscribe A</md-button>
</script>
<script type="text/ng-template" id="/boxb">
BoxB - Message Listener: </br>
<strong>{{boxB.msg}}</strong></br>
<md-button ng-click='boxB.unsubcribe()' class='md-warn'>Unsubscribe B</md-button>
</script>
<md-content class='md-padding'>
<h3>
{{name}}
</h3>
<label>Enter Text To Broadcast</label>
<input ng-model='msg'/></br>
<md-button class='md-primary' ng-click='broadcastFn()'>Broadcast</md-button></br>
<h4>
Components
</h4>
<box-a></box-a></br>
<box-b></box-b>
</md-content>
</div><!--end app-->
var app = angular.module('myApp', ['ngMaterial']);
app.controller('mainCtrl', function($scope,msgService) {
$scope.name = "Observer App Example";
$scope.msg = 'Message';
$scope.broadcastFn = function(){
msgService.broadcast($scope.msg);
}
});
app.component("boxA", {
bindings: {},
controller: function(msgService) {
var boxA = this;
boxA.msgService = msgService;
boxA.msg = '';
boxA.msgService.subscribe(function(obj) {
console.log('Listerner A');
boxA.msg = obj;
});
boxA.unsubscribe=function(){
};
},
controllerAs: 'boxA',
templateUrl: "/boxa"
})
app.component("boxB", {
bindings: {},
controller: function(msgService) {
var boxB = this;
boxB.msgService = msgService;
boxB.msg = '';
boxB.msgService.subscribe(function(obj) {
console.log('Listerner B');
boxB.msg = obj;
});
boxB.unsubscribe=function(){
};
},
controllerAs: 'boxB',
templateUrl: "/boxb"
})
app.factory('msgService', ['$http', function($http){
var msgSubject = new Rx.ReplaySubject();
return{
subscribe:function(subscription){
msgSubject.subscribe(subscription);
},
broadcast:function(msg){
console.log('success');
msgSubject.onNext(msg);
}
}
}])
As per my comment above the new RxJs 5 Beta now changed from subscription.dispose() to subscription.unsubscribe() Please refer to here https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md#subscription-dispose-is-now-unsubscribe
Please see updated fiddle: here
the subscribe function returns a Disposable to work with and you must first return the subscription from your factory (line 60):
subscribe: function(subscription){
return msgSubject.subscribe(subscription);
}
This will let you store your subscription in each controller to work with in the future. (line 21 & 42)
var boxASubscription = boxA.msgService.subscribe(function(obj) {
console.log('Listerner A');
boxA.msg = obj;
});
You can then call the dispose method on the subscription when you want to unsubscribe:
boxA.unsubscribe = function(){
console.log('Unsubscribe A');
boxASubscription.dispose();
};
n.b.
For some reason I couldn't get your demo to work with <md-button> so I changed this to <button> for the sake of the demo.

Factory value not updated in model ...what I am doing wrong?

I am new to angular-js. I have two controllers (welcomeContoller,productController) and both handling the same model within the factory.
When the model getting updating by one controller(productController) it should reflect the update in another controller. (welcomeContoller)
But its not happening now.
HTML code :
<body ng-app="myApp">
<div ng-controller="welcomeContoller">
{{totalProductCnt}}
</div>
<div ng-controller="productController">
<div class="addRemoveCart">
<span class="pull-left glyphicon glyphicon-minus" ng-click="removeProduct()"></span>
<span class="pull-right glyphicon glyphicon-plus" ng-click="addProduct(1)"></span>
</div>
</div>
JS code
var myApp = angular.module("myApp", ['ui.bootstrap']);
myApp.factory("productCountFactory", function() {
return {
totalProducts:0
};
});
myApp.controller("welcomeContoller", function($scope, productCountFactory)
{
$scope.totalProductCnt = productCountFactory.totalProducts;
});
myApp.controller("productController", function($scope, productCountFactory) {
$scope.addProduct = function() {
productCountFactory.totalProducts++;
alert(productCountFactory.totalProducts);
};
$scope.removeProduct = function() {
if(productCountFactory.totalProducts >=1)
productCountFactory.totalProducts--;
alert(productCountFactory.totalProducts);
};
});
Even after the addProduct is called the totalProductCnt is displaying as zero. I want to display the value for each increment.
Plunkr Link
Put the factory object reference on scope:
myApp.controller("welcomeContoller", function($scope, productCountFactory) {
$scope.productCountFactory = productCountFactory;
});
Watch the property of the object.
{{productCountFactory.totalProducts}}
The DEMO on PLNKR.
By putting a reference on scope, on every digest cycle the watcher looks up the value of the property and updates the DOM if there is a change.
The totalProductCnt from your welcomeController isn't updated because it is assigned only once when the controller is created.
You can use several solutions to refresh the displayed value. Use a getter for your totalProducts in the factory :
myApp.factory("productCountFactory", function() {
var totalProducts = 0;
return {
getTotalProducts: function() {
return totalProducts;
},
addProduct: function() {
totalProducts++;
},
removeProduct: function() {
totalProducts--;
}
};
});
myApp.controller("welcomeContoller", function($scope, productCountFactory) {
$scope.getTotalProducts = productCountFactory.getTotalProducts;
});
myApp.controller("productController", function($scope, productCountFactory) {
$scope.addProduct = function() {
productCountFactory.addProduct();
};
$scope.removeProduct = function() {
if (productCountFactory.getTotalProducts() >= 1)
productCountFactory.removeProduct();
};
});
And update the view accordingly:
<div ng-controller="welcomeContoller">
{{getTotalProducts()}}
</div>
Plunkr Link

How to implement loading spinner to inappbrowser in ionic framework

im currently working in ionic framework with inappbrowser but any time i open the external url link it open another broswer but i want it indicate loading spinner so users will know it is loading, i dont know want it to open with system browser
<div class="list">
<a class="item item-avatar" href="#" ng-click="loadData()" onclick="window.open('http://www.mysite', '_blank', 'location=yes'); return false; ">
<img src="img/be1.png">
<h2>site here</h2>
</a>
</div>
and my controller
.controller('MyCtrl', function($scope, $ionicLoading, $timeout) {
$scope.myTitle = 'Loading Sample';
$scope.loadingIndicator;
$scope.counter = 0;
$scope.loadData = function() {
$scope.loadingIndicator = $ionicLoading.show({
template: '<ion-spinner icon="spiral"></ion-spinner>'
});
$timeout(function() {
$ionicLoading.hide();
}, 1500);
};
})
thanks
In loadData() itself add
var ref=window.open('http://www.mysite', '_blank', 'location=no');
(location=no to hide url bar)
ref.addEventListener('loadstart', function() { $ionicLoading.show() });
ref.addEventListener('loadstop', function() { $ionicLoading.hide() });

Resources