jQuery
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
$('.box').bind('mousedown', function(){
alert('box class clicked');
});
angular
<div ng-app="myApp" >
<div data-ng-controller="myCtrl">
<div ng-click="boxClick()" class="box"></div>
<div ng-click="boxClick()" class="box"></div>
<div ng-click="boxClick()" class="box"></div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxClick = function(){
alert('box class clicked');
}
});
Now I am learning AngularJS, if we see this, short and crispy will be jQuery, for a single click event we are writing these much of line code in AngularJS, can anyone help me to write short as much as jQuery, how to select DOM element in AngularJS like jQuery, I am using ng-click to trigger click event in AngularJS, without that can I able to trigger click event in script tag itself. Thanks for replies in advance
You can do it by using directive. this is a standard way in angularjs for this kind of situation.
The sample look like
var app = angular.module('myApp', []);
app.directive('myDomDirective', function () {
return {
link: function ($scope, element, attrs) {
element.bind('click', function () {
alert('You clicked me!');
});
element.bind('mouseenter', function () {
alert('You mouse entered me!');
});
element.bind('mouseleave', function () {
alert('You mouse leaved me!');
});
}
};
});
app.controller('myCtrl', function($scope) {
// do what you want like service calls and binding
});
then call the directives in your any tag
<div ng-app="myApp" >
<div data-ng-controller="myCtrl">
<div my-dom-directive class="box"></div>
<div my-dom-directive class="box"></div>
<div my-dom-directive class="box"></div>
</div>
</div>
Please take a look at this document for more details
Some of the things i want you to notice that when you are working on DOM objects then it is better to do all the stuff in angular directives. As suggested in the answer.
i have created a demo and used this way:
<div ng-app="myApp" >
<div data-ng-controller="myCtrl">
<div ng-btn class="box">Btn1</div>
<div ng-btn class="box">Btn2</div>
<div ng-btn class="box">Btn3</div>
</div>
</div>
and controller in app.js:
app.controller('myCtrl', function($scope) {
$scope.boxClick = function(){ alert('clicked'); };
});
and directive in the app.js:
app.directive('ngBtn', function(){
return {
link:function(scope, element, attrs){
angular.element(element).on('click', scope.boxClick);
}
};
});
Check this sample demo at plunkr
In this answer you can see we have a controller myCtrl in the js and function boxClick is in the $scope of current controller, which alerts a message.
Now if you see the markup you can see a directive named ng-btn which we have used in the directive with the camelCase naming convention in angular with ngBtn in the module.
Now in the directive you can see it returns an object which links to a callback function with three params (scope, element, attrs), where scope is the current controller's scope, element is the one which has the ng-btn attribute. Now using jqLite in the angular.element() you can bind the event on the element and you can see the message poping out.
Related
I'm trying to do angular (1.3.14) directive to handle scrolling event on element like this
var app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
console.log(element.className); // return 'undefined'
element.on('scroll', function(e) {
console.log('scroll'); //not working
});
element.on('click', function(e) {
console.log('click'); //working
});
}
}
});
My problem is that scroll event doesn't fire. Every other event like clicking is normaly working, but scrolling not. Also when I try to get class of element I get 'undefined' and my element has class. It's html:
<body ng-app="myApp" ng-controller="myCtrl" ng-keydown="keyListener($event)">
<section class="dark content second" scroll="">
</section>
</body>
I don't know what can be wrong here.
Your directive is right, I've made a test with an internal div in your section with some classes to make it scrollable
<section class="dark content second" scroll="">
Hi
<div class="internal">
Something
</div>
</section>
CSS
.second{
background-color: red;
max-height: 150px;
overflow-y:scroll;
}
.internal{
height: 200px;
}
And the event works perfectly! You just have to make your <section> scrollable or apply the directive in the body/html tag. Here's the Plunker example that I've tested http://plnkr.co/edit/hp2BbnLeGjtwIbfi2mqZ?p=preview
Try this
console.log(attrs.class);
element.bind('scroll', function() {
console.log('scroll');
});
I am currently using an angular directive to alert the user of unsaved changes if they try to close the tab or browser. Now, I want to add a condition to that directive where if it is a url change within the site, to trigger a custom modal. Is it possible to store the code for this modal in the directive template so that I don't have to copy it to the bottom of each view? Here is my directive so far:
.directive('confirmOnExit', function() {
return {
restrict: "E",
link: function($scope, elem, attrs) {
window.onbeforeunload = function(){
if ($scope.currentForm.$dirty) {
return "You have unsaved changes, are you sure you want to leave the page?";
}
}
$scope.$on('$stateChangeStart', function(event, next, current) {
if ($scope.currentForm.$dirty) {
$scope.showModal = true;
}
});
},
template: "<div id='myModal' class='modal-background' ng-show='showModal'>
<div class='modal-window'>
<div class='modal-text-container'>
<div class='modal-text'>You have unsaved changes. Do you still want to continue?</div>
</div>
<div class='btn-container btn-group'>
<button type='button' class='btn btn-teal' ng-click='yes()'>Yes</button>
<button type='button' class='btn btn-blue' ng-click='no()'>No</button>
</div>
</div>
</div>"
};
})
And the HTML:
<form name="currentForm" ng-model="currentForm" confirm-on-exit>
<input type="text" ng-model="input1" />
<input type="text" ng-model="input2" />
<input type="text" ng-model="input3" />
<input type="text" ng-model="input4" />
<input type="submit" ng-click="saveChanges()" />
</form>
I would suggest you to not store the code in the directive. There are multiple ways to achieve it and the here is the cleaner way of achieving this.
Define a global controller either in <html>, or <body> tag so that it's scope is available throughout your app and do the following in that global controller:
myApp.controller("GlobalController", function($scope) {
// Avoid scope inheritance problem
$scope.globalData = {}
$scope.showMyModal = function () {
$scope.globalData.showModal = true;
}
$scope.hideMyModal = function () {
$scope.globalData.showModal = false;
}
});
Now in your main HTML (like index.html), put the controller and that template:
<body data-ng-controller="GlobalController">
<!-- other content -->
<div id='myModal' class='modal-background' ng-show='globalData.showModal'>
<div class='modal-window'>
<div class='modal-text-container'>
<div class='modal-text'>You have unsaved changes. Do you still want to continue?</div>
</div>
<div class='btn-container btn-group'>
<button type='button' class='btn btn-teal' ng-click='yes()'>Yes</button>
<button type='button' class='btn btn-blue' ng-click='no()'>No</button>
</div>
</div>
</div>
</body>
And there is two problems with your directive. Modified directive looks like:
myApp.directive('confirmOnExit', function() {
return {
restrict: "A",
link: function ($scope, elem, attrs) {
window.onbeforeunload = function () {
if ($scope.currentForm.$dirty) {
return "You have unsaved changes, are you sure you want to leave the page?";
}
};
$scope.$on('$stateChangeStart', function (event, next, current) {
if ($scope.currentForm.$dirty) {
$scope.showMyModal();
event.preventDefault(); // this is required
}
});
}
}
});
The first problem was that you have to use restrict: 'A' since you are using the directive as attribute directive and you have to mention event.preventDefault(); otherwise your state navigation will not be prevented.
Now, we are calling that showMyModal method in the directive and that will be accessible since the directive's scope will inherit it's parent scope and so on.
The another way you could achieve the same using $on and $broadcast to pass the message.
I've read Angular UI Bootstrap adding a close button and show hidden div on ng-click within ng-repeat. I'd like to use the solution from the latter article and apply it to the problem stated in the first article. In essence, I want to be able to close an Angular UI Bootstrap popover with ng-show or ng-click.
I have an example piece of code to illustrate this. This code just applies a CSS class to a particular element whenever it is clicked, and removes it when it is clicked again:
<div ng-class="{'gray-inset-border': style}">
<div ng-click="style=!style"></div>
</div>
Whenever an element containing a popover is clicked, a popover template is created. In the Chrome DOM inspector, the opening tag looks like this:
<div class="popover ng-isolate-scope right fade in"
tooltip-animation-class="fade" tooltip-classes=""
ng-class="{ in: isOpen() }" popover-template-popup="" title=""
content-exp="contentExp()" placement="right" popup-class="" animation="animation"
is-open="isOpen" origin-scope="origScope"
style="top: 317.5px; left: 541.8125px; display: block;">
Notice the ng-class="{in: isOpen()}". I am assuming that this controls whether the popover is open or not, and want to use the same ng-click method as in the example above, and apply it to a button within the popover. However, when I tried that, it didn't work. I also can't find the popover template anywhere in the ui-bootstrap-tpls.js code. As far as I know, popover creation is voodoo magic.
It's also frustrating that Angular UI Bootstrap doesn't have this functionality already. I've been trying to solve this problem off and on for over a week now, and every "solution" I have seen doesn't seem to work for me.
Am I understanding the ng-class="{in: isOpen()}" correctly? Where do I edit the popover template to add a close button?
This was solved by #ognus on a GitHub thread.
He stated:
I've found that using a simple custom directive worked best for my use case. I just want to be able to close the popover from within the popover template.
The directive exposes scope.toggle method that user custom trigger to open and close popover. I'm then using this method in the popover template.
There is a plnkr that I adapted to test my own issue. The solution involved creating a directive (of course).
HTML
<!DOCTYPE html>
<html ng-app="main">
<head>
<script data-require="angular.js#1.x" data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js"></script>
<script data-require="ui-bootstrap#0.13.0" data-semver="0.13.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.min.js"></script>
<link data-require="bootstrap-css#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<script src="popoverToggle.js"></script>
<script src="script.js"></script>
</head>
<body style="margin: 50px">
<!-- Show popover link -->
<a
href=""
popover-placement="bottom"
popover-trigger="open"
popover="Lorem ipsum dolor sit amet, consectetur."
popover-title="This is a title"
popover-toggle>
Show popover</a>
<div popover-placement="bottom" popover-trigger="open"
popover-template="'popover-template.html'" popover-toggle>Show Popover 2</div>
</body>
</html>
popoverToggle directive
angular.module('main')
.config(function($tooltipProvider) {
$tooltipProvider.setTriggers({'open': 'close'});
})
.directive('popoverToggle', function($timeout) {
return {
scope: true,
link: function(scope, element, attrs) {
scope.toggle = function() {
$timeout(function() {
element.triggerHandler(scope.openned ? 'close' : 'open');
scope.openned = !scope.openned;
});
};
return element.on('click', scope.toggle);
}
};
});
Popover template
<p>Are you sure you want to remove this item?</p>
<a href='' ng-click='remove(item)'>Yes</a>
<div ng-click='toggle()'>No</div>
app = angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
app.controller(
'dataCtrl', function() {
var self = this;
self.data = [
{name: "one", num: 23},
{name: "two", num: 87},
{name: "three", num: 283}
]
return self;
}
)
app.controller(
'myPopoverCtrl', ['$scope',
function($scope) {
// query popover
$scope.myPopover = {
isOpen: false,
templateUrl: 'myPopoverTemplate.html',
open: function open( value ) {
$scope.myPopover.isOpen = true;
$scope.myPopover.data = "(" + value.num + ")";
},
close: function close() {
$scope.myPopover.isOpen = false;
}
};
}
]);
<body ng-app="ui.bootstrap.demo" class='container'>
<div ng-controller='dataCtrl as dc' >
<li ng-repeat="d in dc.data">
{{d.name}}
<a ng-controller="myPopoverCtrl"
popover-template="myPopover.templateUrl"
popover-title="This is a popover"
popover-placement="right"
popover-is-open="myPopover.isOpen"
ng-click="myPopover.open(d)">
pop
</a>
</li>
</div>
<script
type="text/ng-template"
id="myPopoverTemplate.html">
<h2 ng-bind="myPopover.data"/>
<button
class="btn btn-success"
ng-click="myPopover.close()">Close me!</button>
</script>
</body>
Link to the working example
This is solution using another controller for the popover.
this controller opens and closes the popover.
you can also write the directive instead of controller.
Its works fine if data is in repeat.
Let's say I have a DIV with a function specified to be called when clicked on it by ng-click.
Inside this DIV there's a BUTTON which also have a function to be called when clicked on, specified by ng-click.
When I click the button, both the DIV's click and the BUTTON's click functions are called.
How do I make that only the BUTTON's function is called?
I have set up this fiddle for better illustrate what I mean. Below is the code:
HTML:
<body ng-app="Test">
<section ng-controller="TestCtrl as ctrl">
<div class="square" ng-click="ctrl.divClick()">
<span>My text</span>
<button ng-click="ctrl.buttonClick()" >My button</button>
</div>
</section>
</body>
JavaScript:
(function() {
var app = angular.module('Test', []);
app.controller('TestCtrl', [function() {
this.divClick = function() {
alert('div clicked');
};
this.buttonClick = function() {
alert('button clicked');
}
}]);
})();
EDIT:
As suggested by akonsu, I just need to stop the event propagation. This worked for me.
Here's an updated Fiddle showing how it works.
Just stop propagation of the event:
<button ng-click="ctrl.buttonClick($event)">
this.buttonClick = function(e) {
e.stopPropagation();
alert('button clicked');
}
I am new to Angularjs. I've tried a example in here.
file index.html:
<div ng-repeat="data in ctl.dataList">
<div class="col-md-6">
<textarea type="text" ng-mouseover="ctl.mouseOverFunc()" ng-mouseleave="ctl.mouseLeaveFunc()">{{data.value}}</textarea>
<button ng-show="ctl.showCloseBtn">X</button>
</div>
</div>
file app.js:
app.controller('FocusController', function() {
this.showCloseBtn = false;
this.dataList = [{
value: "one"
}, {
value: "two"
}];
this.mouseOverFunc = function() {
this.showCloseBtn = true;
};
this.mouseLeaveFunc = function() {
this.showCloseBtn = false;
};
});
I want to show close button when mouse overed every textarea like facebook chat in this picture. But my issues is when mouse over one of textarea then all X button was showed.
How do i assign dynamic controller to every textarea or how to do like facebook chat ?
Thanks for your help
You can do with CSS as well as AngularJS. I suggest you to do with CSS which is Simple. And Do your ng-click on the button.
This Plunker Demo is using with CSS and added ng-click there. Please check the styles and classes added.
Styles
<style>
.field:hover .btn-close {
display:block;
}
.btn-close {
display:none;
}
</style>
HTML
<div ng-repeat="data in ctl.dataList">
<div class="col-md-7 field">
<textarea></textarea>
<button ng-click="doSomething()" class="btn-close">X</button>
</div>
</div>
This Plunker Demo is with AngilarJS as explained in the other answer by New Dev.
<div ng-repeat="data in ctl.dataList">
<div ng-mouseover="data.showX = true"
ng-mouseleave="data.showX = false">
<textarea></textarea>
<button ng-click="doSomething()" ng-show="data.showX">X</button>
</div>
Typically, it would be best to create a directive for this functionality and encapsulate all the logic of clicking the "x" button, but for simplicity you could also leverage the child scope created by ng-repeat, and do the following:
<div ng-repeat="data in ctl.dataList">
<div ng-mouseover="data.showX = true"
ng-mouseleave="data.showX = false">
<textarea type="text"></textarea>
<button ng-show="data.showX" ng-click="ctl.close(data)">X</button>
</div>
</div>
ng-repeat="item in items" creates a child scope for each item, so you can set values on the child scope.
Here's your modified plunker
EDIT:
As suggested in the comments, if you have nothing more complex than showing or hiding the button, definitely CSS approach is the simplest way to go. Use the above example then as an illustration for how scopes work.