I am trying to implement close on out side click, just like in this example : http://plnkr.co/edit/ybYmHtFavHnN1oD8vsuw?p=preview
But I keep missing something, It is not working in my code.
HTML Directive
<div class='multiDate'>
<div class="dropdown">
<button data-ng-click="show = !show" class="dropbtn">Press</button>
<div id="myDropdown" ng-show="show" class="dropdown-content">
<multiple-date-picker></multiple-date-picker>
</div>
</div>
</div>
HTML Main
<html>
<head>
<script data-require="angularjs#1.6.2" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script>
<script data-require="moment.js#*" data-semver="2.14.1" src="https://npmcdn.com/moment#2.14.1"></script>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://arca-computing.github.io/MultipleDatePicker/stylesheets/multipleDatePicker.css" />
<script src="https://arca-computing.github.io/MultipleDatePicker/javascripts/multipleDatePicker.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="cntrl">
<multi-date></multi-date>
</body>
</html>
JS
var app = angular.module("app", ['multipleDatePicker']);
app.controller("cntrl", function($scope) {
});
app.directive('multiDate', function($document) {
return {
templateUrl: 'multi.html',
replace: true,
link: function(scope, element) {
$document.bind('click', function(event) {
var isClickedElementChildOfPopup = element
.find(event.target)
.length > 0;
if (isClickedElementChildOfPopup)
return;
scope.show = false;
scope.$apply();
});
}
}
});
PLNKR
Your plunker code is pretty much working, except the jquery library is not referenced. Add it before the angular library will do.
<head>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script data-require="angularjs#1.6.2" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script>
<script data-require="moment.js#*" data-semver="2.14.1" src="https://npmcdn.com/moment#2.14.1"></script>
If jquery is not included before angular, angular will use its built in jqLite, which element.find function doesn't work exactly like the one in jquery.
First of all angularjs by default use jquery which was included into page before angularjs or jqLite in other cases.
Secondly jqLite has not all methods, even more, some method's behavior can be different from jquery. See documentation for angular.element
Your example doesn't work due find() - Limited to lookups by tag name. To fix it you have to change condition for isClickedElementChildOfPopup one of possible solutions
var isClickedElementChildOfPopup = event.target.closest(".dropdown") !== null;
but be careful Browser support closest method and polyfill.
Related
Can some body explain me why below directive is not getting called? Its getting called if I directly add the directive to the button. I tried it adding using $timeout but still no luck.
<html>
<head>
<title>AngularJS</title>
<script src = "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script type="text/javascript">
var app = angular.module('MyApp',[]);
app.controller('MyCtrl',function($scope,$timeout){
document.getElementById('myBtn').setAttribute('my-directive','');
});
app.directive('myDirecitive',function(){
function linkFn (scope,element,attrs){
element.bind('click',function(){
alert('Clicked');
});
}
return {
restrict:'A',
link:linkFn
}
});
</script>
</head>
<body ng-app="MyApp", ng-controller="MyCtrl">
<button id="myBtn">Test</button>
</body>
</html>
app.directive('myDirecitive',function(){
should be
app.directive('myDirective',function(){
it's best not to query the DOM inside the controller. Don't do this
document.getElementById('myBtn').setAttribute('my-directive','');
my-directive was created as an attribute directive, so it would be best to add that directly to the element like this.
<button id="myBtn" my-directive>Test</button>
I created a plunker
https://plnkr.co/edit/pispsMzbJIxrIDyIv81N?p=preview
I am new to angularjs and I want to know why it isn't working.
The code has a flaw and am not sure about the same.
Thinking from java perspective,httpController defined has nested function defined inside.
Here it is my code
index.html
<!DOCTYPE html>
<html >
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="myapp" ng-controller="HelloController">
<h2>{{message}}</h2>
</div>
<div ng-app="httpService" ng-controller="httpController">
<div>FirstName:{{user.name}}</div>
</div>
</body>
</html>
Script.js
var app = angular.module("myapp", []);
app.controller("HelloController", function($scope) {
$scope.message = "Hello, AngularJS";
});
var httpApp=angular.module("httpService",[]);
httpApp.controller("httpController",function($scope,$http){
var onUserComplete=function(response){
$scope.user=""response.data"";
}
$http.get("https://api.github.com/users/rob").then(onUserComplete);
}
);
Only one ng-app will be automatically bootstrapped on your page. That's why if you remove the first ngApp directive, the second one will work.
var httpApp = angular.module("httpService", []);
httpApp.controller("httpController", function($scope, $http) {
var onUserComplete = function(response) {
$scope.user = response.data;
}
$http.get("https://api.github.com/users/rob").then(onUserComplete);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="httpService" ng-controller="httpController">
<div>FirstName: {{user.name}}</div>
</div>
NOTE: You have a typo in your callback, remove ""s around your response.data. Also, since you are using Angular 1.5.6, you don't need to specify dependencies/inject your $http service to make your code work.
https://plnkr.co/edit/LyWCLeBeyHPzjys3LOcr?p=preview
<body ng-app="httpService">
<div ng-controller="httpController">
<div>FirstName: {{user.key}}</div>
</div>
</body>
This link is working fine...just try it out
Do not use ng-app more than once in your program...Your code would not work
I've a bootstrap alert that appears after some operation is completed,but I want it to close after two or more seconds,how can I achieve this effect?I'm using Angular.js and I've only found solutions in jQuery.
Thanks.
Angular bootstrap provides an option for alert directive dismiss-on-timeout. It accepts timeout in milliseconds. This attribute requires the presence of the close attribute.
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('AlertDemoCtrl', function($scope) {
$scope.show = true;
$scope.closeAlert = function(index) {
$scope.show = false;
};
});
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.3.3.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="AlertDemoCtrl">
<uib-alert type="danger" close="closeAlert()" ng-if="show" dismiss-on-timeout="4000">Oh snap! Change a few things up and try submitting again.</uib-alert>
</div>
</body>
</html>
I have a textarea and a span. The textarea has an ngBlur which calls a function. I only want that function to run its code when the cause of the blur wasn't a click on the span. How can I do that?
http://plnkr.co/edit/ENvuujbychxYum1EMmkf?p=preview
HTML
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script data-require="angular.js#1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller='MainController as vm'>
<textarea ng-blur='vm.selective()'></textarea>
<span>span</span>
</body>
</html>
JS
angular
.module('app', [])
.controller('MainController', MainController)
;
function MainController() {
vm.focus = true;
vm.onBlur = function() {
// HOW DO I DO THIS?
// if (spanIsClicked) {
// return;
// }
vm.focus = false;
};
}
I believe you can pass in the DOM element as an argument in angular, looking like :
vm.onBlur = function($event){}
You could then access the event by using event.target. I know this works with ng-click so I'm not totally positive if the same rules apply for ng-blur.
I have this jQuery selectors. Everything was working fine but just by adding and initializing angular, the multiselect stops working. You can try removing everything that is not necesary and you'll see this happens:
(I don't know why github's urls are not working here, but you can download the file if needed, as that is not the problem I'm trying to depict)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>SPIROOX - Campaigns</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css" />
<link rel="stylesheet" href="bootstrap-multiselect/dist/css/bootstrap-multiselect.css" type="text/css" />
</head>
<body ng-app="campaign_listing">
<div class="content" ng-controller="campaign_list_controller as ctrl">
<h2>Campaign Administration</h2>
+
<div class="filters">
<select id="multiselect_status" ng-model="ctrl.filters.status" ng-change="ctrl.update_fields()" multiple="multiple">
<option value="active">Active</option>
<option value="suspended">Suspended</option>
<option value="closed">Closed</option>
</select>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script type="text/javascript" src="bootstrap-multiselect/dist/js/bootstrap-multiselect.js"></script>
<script>
$(document).ready(function() {
$('#multiselect_status').multiselect({
includeSelectAllOption: true,
enableFiltering: true,
nonSelectedText: 'Status'
});
});
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"></script>
<script>
var my_app = angular.module("campaign_listing", []);
var controllers = {};
controllers.campaign_list_controller = function($http) {
this.filters = {
status: 'active',
client: null
};
var campaigns = {};
this.update_fields = function() {
console.log("update!");
console.log(this.filters);
}
}
my_app.controller(controllers);
</script>
</body>
</html>
As mentioned in the comments add the jQuery plugin code in a directive and remove the document.ready stuff because it's not needed in the directive.
The DOM is ready when you're adding the plugin code in directive's link method.
I haven't tested the rest of your angular code because it looks too complicated and I've re-coded it to improve readability. (Maybe your code is working but I wouldn't code it like this.)
Please have a look at the demo below or in this jsfiddle.
Update 29.09.15
For a better understanding of directives please read the documentation about directives to get the basics for custom directives.
Anyway here is the explanation to the directive:
The multiselect directive is added as attribute directive (restrict: 'A') to the select tag and so element inside of link function is the select tag where you'd like to apply the jQuery plugin. (Inside of link it's safe to use jQuery functions but I'd recommend to reduce the usage to a miminimum.)
Search for link, compile, controller in google or here at SO to learn more about directives. There is a question for the difference between them here at SO.
You could also create an element directive with template then you can add the select tag into the directive and pass your selection with two-way binding. That's probably better here because it's more reusable.
angular.module('campaignListing', [])
.controller('CampaignListController', CampaignListController)
.directive('multiselect', MultiSelectDirective);
function CampaignListController($http) {
this.filters = {
status: 'active',
client: null
};
var campaigns = {};
this.update_fields = function () {
console.log("update!");
console.log(this.filters);
}
}
function MultiSelectDirective() {
return {
restrict: 'A',
link: function (scope, element) {
$(element).multiselect({
includeSelectAllOption: true,
enableFiltering: true,
nonSelectedText: 'Status'
});
}
}
}
<link href="https://cdn.rawgit.com/davidstutz/bootstrap-multiselect/master/dist/css/bootstrap-multiselect.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davidstutz/bootstrap-multiselect/master/dist/js/bootstrap-multiselect.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<div ng-app="campaignListing">
<div>
<div class="content" ng-controller="CampaignListController as ctrl">
<h2>Campaign Administration</h2>
+
<div class="filters">
<select id="multiselect_status" multiselect ng-model="ctrl.filters.status" ng-change="ctrl.update_fields()" multiple="multiple">
<option value="active">Active</option>
<option value="suspended">Suspended</option>
<option value="closed">Closed</option>
</select>
</div>
</div>
</div>
</div>