angular js scope watch not updating bootstrap badge counter - angularjs

I am an angular newbie. Fiddling around with $scope.
I have this snippet in my main view:
<div ng-controller="MainCtrl" class="ng-scope">
<ul class="nav navbar-nav navbar-right">
<li></span><span class="badge">{{ badgeCount }}</span></li>
</ul>
</div>
....
<div class="container">
<ui-view></ui-view>
</div>
home.html gets loaded through ui-view.
Inside home.html, I have
<div ng-repeat='item in items'>
<td> <button type="submit" class="btn btn-default btn-lg btn-success" ng-model="orderCnt" ng-click="placeOrder(item.desc)"><span class="glyphicon glyphicon-cutlery"></span></button> </td>
</div>
The controller is MainCtrl.
My controller is:
controller('MainCtrl', ['$scope', function($scope, menus) {
$scope.items = [];
$scope.badgeCount = 0;
$scope.orderCnt = 0;
console.log("badgecount=",$scope.badgeCount)
console.log("ordercnt=",$scope.orderCnt)
$scope.placeOrder = function(value) {
$scope.orderCnt ++;
console.log(value)
console.log($scope.orderCnt)
console.log("ng click")
};
$scope.$watch('orderCnt', function(newVal, oldVal){
console.log(newVal + " " + oldVal);
$scope.badgeCount++;
console.log("watch")
},true);
For any ng-click on placeOrder, I would expect the badgeCount to get updated on the shopping cart icon as well. Its not happening. Do I need to emit/broadcast this since its a different view? I was thinking since both have same controllers, same $scope would be bound. Any help would be appreciated.

Is your container div a child of the <div ng-controller="MainCtrl" class="ng-scope">? If not then they will have different scopes. Changes in one will not be seen in another.
Some other points
you don't need ng-model defined on the button, doesn't make sense cause it doesn't get changed.
why are you watching orderCnt in this case? It only changes in scope.placeOrder so you can call $scope.badgeCount++; in scope.placeOrder
EDIT: If you want the view to have the same scope you can place it as a child of the main controller. Also note that you're missing a > in your definition of <a href"#"
<body ng-controller="MainCtrl">
<ul class="nav navbar-nav navbar-right">
<li><span class="glyphicon glyphicon-shopping-cart gi-2x"></span><span class="badge">{{ badgeCount }}</span></li>
</ul>
<div class="container">
<ui-view></ui-view>
</div>
</body>

Related

controller scope not working in separate html page

I tried to hide some menus using a controller. Here is my element container where the menu will be loaded.
<div class="page-content" ng-controller = "menuController">
<div id="Menu" > </div>
<div ng-view> </div>
</div>
<script>
$(function(){
$("#Menu").load("Menu.html");
});
app.controller("menuController", function($scope) {
$scope.showMenu = false;
});
</script>
I wrote the menu in seperate html file.
<div class="category-content no-padding">
<ul ng-show= "showMenu">
<li><i class="fa fa-h-square text-brown" aria-hidden="true"></i><span>Organization</span>
</li>
<li><i class="fa fa-hospital-o text-brown" aria-hidden="true"></i><span>Clinic</span>
</li>
<li><i class="fa fa-user text-brown" aria-hidden="true"></i><span >User</span>
</li>
</ul>
</div>
But for me scope variable declared in the controller does not have any impact on menu. Please help me to overcome this.
Thanks for your valuable time.
Mixing Jquery code with Angular code is not very good.
You can use angular's ng-include directive to load your menu:
<div class="page-content" ng-controller = "menuController">
<div ng-include="'Menu.html'" > </div>
<div ng-view> </div>
</div>
Depending on the location of Menu.html, you may have to precise the entire path, for example:
<div> ng-include="'folder/subfolder/Menu.html'" </div>

Angularjs ng-show issue with ng-route

I'm newbie to angular world. I'm trying to create a login page.When the user login, i want to show some contents in the navbar.
Currently i'm using ng-show and ng-route. When i'm not using ng-route, ng-show works fine but when i use ng-route, ng-show is not working .I don't want to use angular-ui-router. What i'm doing wrong. Can anyone help me
Angular Config
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'login.html',
controller: 'ctrl'
})
.when('/logged', {
templateUrl: 'logged.html',
controller: 'ctrl'
})
otherwise({
redirectTo: '/'
});
}]);
app.controller("ctrl",['$scope','$http','$location',function($scope,$http,$location){
$scope.myvalue2=false;
$scope.login = function()
{
//here i making the $http.post to login on success im changing $scope.myvalue2=true;
}
}]);
HTML
<nav class="navbar-default navbar-dark bg-primary">
<div class="navbar">
<div class="container-fluid navi">
<div class="navbar-header" style="padding-bottom:10px">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<ul class="navbar-brand " style="list-style:none;padding-top:10px;"><li>name</li></ul>
</div>
<div ng-show="myvalue2" class="ng-cloak">
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1" style="padding-top:10px">
<ul class="nav navbar-nav">
<li>About</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#" style="font-size:14px;">Settings</a></li>
</ul>
</div>
</div>
</div>
</div>
</nav>
I don't think that ngRoute would have any impact on ng-show. It's working fine check this working demo :
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.myvalue2 =false;
$scope.login = function() {
$scope.myvalue2=true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<a ng-click="login()">Login</a>
<div ng-show="myvalue2">
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1" style="padding-top:10px">
<ul class="nav navbar-nav">
<li>About</li>
<li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#" style="font-size:14px;">Settings</a></li>
</ul>
</div>
</div>
</div>
You're going to want to use the digest cycle here, and do away with ng-show, since its use gets easily mistaken for the more elegant and simpler-to-understand ng-if.
In short:
AJAX calls will trigger a digest cycle.
ng-if will actively remove DOM if its condition is not met, thus drawing less DOM.
Changing the value on an AJAX call in an ng-if will work instead of hiding the DOM element, since it'll be eligible to be visible anyway.
The ng-cloak class is throwing me off; you probably don't need that there, since with ng-if, it won't be anywhere in the DOM until you actually need it.
What your controller might look like:
app.controller("ctrl", [
'$scope',
'$http',
'$location',
function ($scope, $http, $location) {
$scope.myvalue2 = false;
$scope.login = function () {
$http.get('/path/to/your/request', function(data) {
$scope.myvalue2 = true;
});
}
}]);
What your DOM would need to change to (and yes, I prefer absolute truth to truthiness):
<div ng-if="myvalue2 === true">
This will help you,
<div ng-app="myApp" ng-controller="myCtrl">
<button class="btn btn-success" type="text" ng-model="firstName" ng-show="display" ng-click="display=!display"> BUTTON 1</button>
<br />
<button class="btn btn-warning" ng-click="display=!display" ng-model="lastName" ng-show="!display"> BUTTON 2
</button>
</div>
DEMO

How to access a ngform name from controller?

I need to check if the elements on the current html page (being rendered using ui-view) are dirty or pristine before I navigate to next tab.
Parent page:
<div class="inner-menu">
<nav>
<div>
<ul class="nav nav-tabs edit-menu" role="tablist">
<!-- location 1 -->
<li ng-repeat="innerTab in innerTabListArr" ng-click="switchTab($index, $event)">
<a role="tab" data-toggle="tab" href="">{{innerTab.text}}</a>
</li>
</ul>
</div>
</nav>
<div ui-view="innerTabHolder" name="currForm"></div>
</div>
and the HTML template that will be rendered to innerTabHolder view is :
<div class="edit-general" id="General">
<div class="modal-dialog modal-lg">
<form class="form-horizontal" name="generalForm">
<label for="inputL3" class="control-label">Text</label>
<div class="col-sm-4">
<input type="text" class="form-control" ng-model="gn.myMdl">
</div>
<div class="box-footer">
<div class="row">
<div class="col-sm-10">
<!-- location 2 -->
<button class="btn" type="button" ng-click="switchTab(generalForm, $event)"> BCK </button>
<button class="btn" type="button" ng-click="saveGen()">Save Above</button>
<button class="btn" type="button" ng-click="switchTab(generalForm, $event)"> FWD </button>
</div>
</div>
</div>
</form>
</div>
</div>
There are multiple tabs that will get rendered into the view. And this is the controller I have:
myApp.controller('compTabCtrl',[ '$rootScope', '$scope', '$state', 'mainWebService',
function($rootScope, $scope, $state, mainWebService){
$scope.innerTabListArr = [{"text" : "Tab 1"},{"text" : "Tab 2"}];
$scope.switchInnerTab = function(tabId, event){
};
}]);
Ok, so this is basic outline and I believe, I have covered all parts. Now, my issue is I am not able to pass the form : "generalForm" into switchTab function at location 1 where as I can do the same at location 2.
I am using the form's $dirty and $pristine to check if the user has made any changes to the form. So, while clicking on the tab for navigation, the form becomes undefined.
How do I access the $dirty property of sub-view in controller.
Plunker for demo :
https://plnkr.co/edit/06F5JfXltinyxrZbbc14?p=preview
When you are trying to access the variable always use $scope
access curForm using
$scope.curForm.$dirty

AngularJS & Bootstrap Modal - loading template outside controller

I have a dialog which is being used in 3 scenarios within the same page. I have created a controller similar to the below:
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Im a modal!</h3>
</div>
<div class="modal-body">
<ul>
<li ng-repeat="item in items">
<a ng-click="selected.item = item">{{ item }}</a>
</li>
</ul>
Selected: <b>{{ selected.item }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
The issue is, that since this dialog is being used in 3 different parts of the same page, I have a problem with the template. When I put the html template outside of the controller, at the very end of the page html, it fails and gives me a 404.
However, I do not wish to repeat the same chunk of HTML in 3 places in the same page. Can someone tell me if there's a different way of calling the template which is outside the controller?
A good way to reuse your template is to put it in a separate html file and put its url in templateUrl. So $modal can get it from server every time needed.

Adding ng-click event with jQuery

Being new to Angularjs, I need a bit of help with this issue. I am attempting to add ng-click="getGallery(57)" to a modal tab. Adding via jQuery is not the issue, however I realize when I do this, Angular is not compiling the newly added ng-click. I have a simple controller
function imageGalleryCtrl ($scope, $http) {
//get gallery info on click
$scope.getGallery = function(id)
{
$http.post('/beta/images/get_images',{'id': id}).success(function(data)
{
$scope.images = data.thisGal_images;
$scope.images.galID = id;
});
};
}
I add the ng-click to the element with jQuery
//Edit image tab to use angularjs
$('#image_edit a').attr('ng-click','getGallery(' + settings.id + ')');
How do I force Angular to compile this newly added ng-click?
Thanks!
HTML Modal:
This is the modal that is called when the gallery name is clicked.
<div class="modal fade hide modal-creator" id="imageUploader" tabindex="-1" data-focus-on="input:first">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"></button>
<h3>Create New Gallery</h3>
</div>
<div class="modal-body">
<ul id="myTab" class="nav nav-tabs">
<li id="image_home" class="">
Home
</li>
<li id="image_upload" class="">
Upload Image Gallery
</li>
<li id="image_edit" class="">
Edit Image Gallery
</li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade in" id="home">
<?php include('create.php'); ?>
</div>
<div class="tab-pane fade" id="upload">
<?php include('upload.php'); ?>
</div>
<div class="tab-pane fade" id="edit">
<div class="span9">
<ul id="imageSort" class="gallery-container">
<li ng-repeat="image in images">
<img ng-src="http://images.onlinealbumproofing.com/imageGallery/{{image.galleryID}}/{{image.imageName}}" alt="">
{{image.orgName}}
</li>
</ul>
</div><!-- /span9 -->
</div><!-- /row -->
</div>
</div>
</div><!-- /modal-body -->
<div class="modal-footer">
Close
Next
</div>
</div>
Update
So really attempting to do this the Angular way, and after some studies here is where I am at.
The controller is the same as above and I have updated the tabs on the modal as follows.
<div class="modal-body">
<ul id="myTab" class="nav nav-tabs">
<li id="image_home" class="">
Home
</li>
<li id="image_upload" class="">
Upload Image Gallery
</li>
<li id="image_edit" class="">
<a ng-click="getGallery(57)" href="#edit" data-toggle="tab">Edit Image Gallery</a>
</li>
</ul>
If I hard code the ng-click as above, the tab updates as expected. What I am trying to make happen, is when the modal is called, (#image_edit a) gets a defined ng-click="getGallery(id). I need to tell Angular to look at the ng-click again for the id.
Although I too think that you should try and find another approach, the answer to your question
How do I force Angular to compile this newly added ng-click?
is
// remove and reinsert the element to force angular
// to forget about the current element
$('#button1').replaceWith($('#button1'));
// change ng-click
$('#button1').attr('ng-click','exec2()');
// compile the element
$compile($('#button1'))($scope);
See this working example: http://plnkr.co/edit/SgvQzaY0TyFHD1Mf0c3F?p=preview
Basically what I'm getting at is you want to probably make this happen:
<ul id="imageSort" class="gallery-container">
<li ng-repeat="image in images">
<img
ng-src="http://images.onlinealbumproofing.com/imageGallery/{{image.galleryID}}/{{image.imageName}}"
alt=""
ng-click="getGallery(image.galleryID)"
>
{{image.orgName}}
</li>
</ul>
The problem is I'm unsure of the relationship between the settings.id and the galleryID for a particular image. If you can set up this relationship in the data so it just automatically binds you're in better shape.

Resources