Understanding the working of ngClick and ngDblclick - javascript

I was trying to figure out how ngClick and ngDblclick work in angularjs. The problem is that even while clicking twice, instead of calling doubleclick function once. Angular calls click function twice and double click function once.
HTML:
<div ng-controller="MyCtrl">
<div class="button" ng-click="click()" ng-dblclick="dblclick()">
Click
</div>
<div class="button" ng-click="reset()">
Reset
</div>
<div>
clicked:{{clicked}}
</div>
<div>
double clicked : {{dblclicked}}
</div>
</div>
JS:
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.clicked = 0;
$scope.dblclicked = 0;
$scope.click = function(){
$scope.clicked++;
};
$scope.dblclick = function(){
$scope.dblclicked++;
};
$scope.reset = function(){
$scope.clicked = 0;
$scope.dblclicked = 0;
};
}
JsFiddle here
But this is not the case in jQuery wherein $(someElement).click() and $(someElement).dblclick() work as expected, which seems to be the ideal way to do it.
I have a fair idea that this is happening because they are implemented as directive in angular. Wherein in jQuery it works by listeners.
I see that you can eliminate this by using $evalAsync, but what reckons me is why we need such an extra burden to achieve something which is very obvious.
Can someone tell me how to handle the scenario. Thanks in advance.

Related

How to replace a child div on it's existing parent div using angularjs?

I have the following code.
html:
<div ng-controller="Test">
<div ng-click="first()" ng-hide="seconddiv">First
<div ng-click="second()" ng-show="seconddiv">Second</div>
</div>
</div>
js:
var app = angular.module('app',[]);
app.controller('Test',function($scope){
$scope.first = function(){
alert("first clicked");
}
$scope.second = function(){
alert("second clicked");
}
});
On executing the above code:
a). I should see only First by default(I can see one now: First) - it is fine now
b). then, if I click on First, then it should execute it's first() method, then First should be replaced with Second(on UI) - it's not coming
c). then, if I click on Second, then it should execute it's second() method only, (it should not execute any other methods like first() except second() method) - it's not coming
I request you to please help me regarding this that how can we do this? Thanks in advance!
Please note that Html <div> structure should not change, so it should be same.
Created Fiddle .
Go the Angular Way.
You will have just one function, toggle. Which will toggle the value of variable first from true to false and vice versa.
Depending on value of first you will show either div with content as First or that with content as Second.
You will also refactor your HTML a bit as follows
<div ng-controller="Test">
<div ng-if="first" ng-click="toggle()">First</div>
<div ng-if="!first"ng-click="toggle()">Second</div>
</div>
And in your JS you will do
var app = angular.module('app',[]);
app.controller('Test',function($scope){
$scope.first = true;
$scope.toggle = function(){
$scope.first = !$scope.first;
}
});
====
EDIT:
Alternatively, you don't even need the toggle function. Just use ng-click expression.
<div ng-controller="Test">
<div ng-if="first" ng-click="first=!first">First</div>
<div ng-if="!first"ng-click="first=!first">Second</div>
</div>
And in JS
app.controller('Test',function($scope){
$scope.first = true;
});

AngularJS: Changing variable for an ng-switch using dynamically generated DOM

This is a little difficult to explain since I can't extract the code that I'm having the most difficulty with. The best I can do is a simple fiddle of what I'm trying to accomplish: https://jsfiddle.net/yLkukw5p/
HTML:
<div ng-app = "myApp" ng-controller = "parentController" ng-switch = "properties.selectedMethod">
<div ng-controller = "childController" ng-switch-when = "id">
<a ng-click = "survey()">
Change div
</a>
</div>
<div ng-switch-when = "date">
div changed
</div>
</div>
JS:
var app = angular.module('myApp', []);
app.factory('vars', function() {
var properties = {};
properties.selectedMethod = 'id';
function setselectedMethod(string){
properties.selectedMethod = string;
}
return {
properties : properties,
setselectedMethod : setselectedMethod
};
});
app.controller('parentController', function($scope, vars) {
$scope.properties = vars.properties;
$scope.setSearchMethod = function(method){
vars.setselectedMethod(method);
}
});
app.controller('childController', function($scope, $rootScope, $http, vars) {
$scope.properties = vars.properties;
$scope.survey = function() {
vars.setselectedMethod("date");
}
});
Basically, I want to be able to change the variable value in a factory shared between child and parent controllers. The only hiccup I'm running into is that in my case, the child div is dynamically generated, and that seems to be the only thing different between the fiddle and my code. I have some JavaScript that adds this DOM:
<div onclick = angular.element('#anotherdiv').scope().setSearchMethod('id');> More Info </div>
where anotherdiv is a div within the childController. When I click this div, I know by debugging that it runs the code in the vars factory, but it doesn't update other values? I'm using the "dot" trick so I would think the variables are references and not "shadowing" as some other posts suggested. Any thoughts?
EDIT: Updated the fiddle to be more accurate: https://jsfiddle.net/yLkukw5p/1/
It looks like the onclick function using angular.element is the one causing trouble, but I don't know how to work around it.

Angular Apply already in progress

I am using an angular js plugin called intro.js. It can be found here. What I want to do with this is open up a dropdown when the user clicks on the demo button so that I can show some intro steps for the dropdown items. Here's my html:
<body ng-controller="MainCtrl as ctrl">
<div ng-intro-options="ctrl.IntroOptions"
ng-intro-method="ctrl.CallMe">
<div class="container">
<button class="btn btn-success"
ng-click="ctrl.startHelp()">Help</button>
</div>
</div>
</body>
And my JS:
MainCtrl.prototype.startHelp = function() {
var _this = this;
angular.element('#drop-down-button').trigger('click');
_this.CallMe();
};
I've also tried
angular.element('#drop-down-button').click();
But the same error. The intro works just fine if i remove the angular.element line. However, with that included I get this error. Any idea how to get around this?
I just had to wrap the call inside of a timeout.
MainCtrl.prototype.startHelp = function() {
var _this = this;
_this.$timeout(function() {
angular.element('#drop-down-button').trigger('click');
}, 0, false);
_this.CallMe();
};

Can't get ng-show to show a div after the div's ng-click has hidden it

My hmtl code from my view looks like this:
<div ng-show="show_alert_message" ng-bind-html="alert_message"
class="alert-message-container"
ng-click="show_alert_message=!show_alert_message"></div>
I show the div initially by doing this in the view's controller:
$scope.show_alert_message = true;
The user clicks on the div to close it causing the ng-click to make show_message_alert false. This works great, hiding the div. But if I try to show the div again by running the command again in the controller it doesn't show:
$scope.show_alert_message = true;
It seems as if the ng-click had stopped it being possible to show the div again.
Am I doing something wrong? The scope for the controller $scope.show_alert_message = true; should be identical to the scope of the ng-click="show_alert_message=false" so I can't see why the second $scope.show_alert_message = true; doesn't work whereas the first one does.
I made a snipet and it is working as you wish. Look at your scope to see which scope are you using when you run $scope.show_alert_message = true;. I think this is the place to be fixed.
var $scope = {};
var myApp = angular.module('myApp', []);
myApp.controller('ngShowCtrl', ['$scope', function($scope){
$scope.show_alert_message = true;
$scope.alert_message = "I'm an alert message!"
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="ngShowCtrl">
<div
ng-show="show_alert_message"
ng-bind="alert_message"
class="alert-message-container"
ng-click="show_alert_message=!show_alert_message"
></div>
<button type="button" ng-click="show_alert_message=!show_alert_message">Show/Hide</button>
</div>
use ng-if="show_alert_message" and ng-click="toggle()"
and
$scope.toggle=function(){
setTimeout(function(){
$scope.show_alert_message=! $scope.show_alert_message;
//$scope.$apply();
},0);
}

Hide any html element with Angularjs

With a controller I try to hide any html element that is clicked with function call like this:
<div class="well">
<h4><span class="label label-primary" ng-click="hideThis($event)" id="tag" hidden></span></h4>
<h4><span class="label label-default" ng-click="hideThis($event)" id="tag2" hidden></span></h4>
</div>
and this script should do the work
var App = angular.module('App', []);
App.controller('appCtrl', function($scope) {
$scope.hideThis = function($event) {
$event.target.hide=true;
//Code I've tried:
// $event.target.hide();
// $event.target.hide(true);
};
});
perhaps I'm not using $event.target.etc properties correctly?
ng-if will remove the element from the DOM; ng-hide will hide the element from the display only.
The other two answers already have the gist of it, but don't go into much detail on why other options are being suggested. They also don't incorporate how to relate those directives to the fact that you want things to happen on click.
To start by summarizing:
On ng-click your app should change the $scope.
On $scope changes Angular should change DOM element's visibility.
Let me repeat: your app should update the model (e.g. $scope), never the DOM itself. Let the latter be handled by Angular.
To add some more details...
AngularJS is a framework that handles "data binding" for you, meaning it will (and should) take charge of keeping your model (e.g. $scope) and view (the markup) in synch. You should usually not interfere with this behavior, unless there is a very specific reason to do so. A quite lengthy but interesting read on this and related topics can be found in this answer (which incidentally was answered to a question about when it is okay to use jQuery yourself).
Long story short: don't update the DOM inside your controller / scope.
Instead: work declaratively. Make sure that your controller and scope have all the info needed to base view-decisions (e.g. "show" vs "hide") on. Furthermore, make sure that your view is told when to show/hide based on the scope situation.
For completeness sake, let me end by repeating #JohnManko's suggestions, where the examples also show how you could handle ng-click to change the underlying properties.
The first is using ng-if:
var App = angular.module('App', []);
App.controller('appCtrl', function($scope) {
$scope.isTagOneActive = true;
$scope.isTagTwoActive = true;
$scope.hideTag1 = function() { $scope.isTagOneActive = false; }
$scope.hideTag2 = function() { $scope.isTagTwoActive = false; }
});
h4:hover { cursor: pointer; background-color: pink; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<div ng-app="App" ng-controller="appCtrl">
<h4 ng-if="isTagOneActive" ng-click="hideTag1()" id="tag">Tag One!</h4>
<h4 ng-if="isTagTwoActive" ng-click="hideTag2()" id="tag">Tag Two!</h4>
</div>
This adds/removes elements from the DOM entirely.
To just let AngularJS toggle visibility, use ng-show and/or ng-hide:
var App = angular.module('App', []);
App.controller('appCtrl', function($scope) {
$scope.isTagOneActive = true;
$scope.isTagTwoActive = true;
$scope.hideTag1 = function() { $scope.isTagOneActive = false; }
$scope.hideTag2 = function() { $scope.isTagTwoActive = false; }
});
h4:hover { cursor: pointer; background-color: pink; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<div ng-app="App" ng-controller="appCtrl">
<h4 ng-show="isTagOneActive" ng-click="hideTag1()" id="tag">Tag One!</h4>
<h4 ng-hide="!isTagTwoActive" ng-click="hideTag2()" id="tag">Tag Two!</h4>
</div>
it can be done much easier
<span class="label label-default" ng-show="showTag2=!showTag2" id="tag2" />

Categories

Resources