how to close pop up screen when click out side in screen - angularjs

I make one pop up screen I open pop up screen on button screen .I want to hide pop up screen when I click outside the screen can is this possible ?
code
http://codepen.io/anon/pen/KpLgpm
angular.module('ionic.example', ['ionic'])
.controller('PopupCtrl', function($scope, $timeout, $q, $ionicPopup) {
$scope.showPopup = function() {
$scope.data = {}
$scope.setDefault = function () {
console.log('Default set', arguments);
$scope.$onClose({ test: 'hello' });
};
$scope.btns = [
{
label: "Hi",
value: "hi"
},
{
label: "Hello",
value: "hello"
}
];
$ionicPopup.show({
template: '',
title: 'Pick a default value',
scope: $scope,
buttons: [
{
text: 'Awesome',
onTap: function(e) { return 'awesome'; }
},
{ text: 'Cool', onTap: function(e) { return 'cool'; } },
{ text: 'Cooler', onTap: function(e) { return 'cooler'; } },
{ text: 'Stuff', onTap: function(e) { return 'stuff'; } }
]
}).then(function(res) {
console.log('Tapped!', res);
}, function(err) {
console.log('Err:', err);
}, function(msg) {
console.log('message:', msg);
});
};
});

angular.element( $window ).on( "click", function( event ) {
if( angular.element( "#popdiv" ).has( event.srcElement || event.target ).length === 0 ) {
// hide popup
}} );

I've found a solution, called "ionic-close-popup".
Install this in your project, add in your index.html, inject in the controller, and register the popup:
https://libraries.io/bower/ionic-close-popup

You can create a directive with below code
angular.module("testapp").directive('clickAnywhereButHere', ["$document", function ($document) {
//click-any-where-but-here
return {
restrict: 'A',
link: function (scope, elem, attr, ctrl) {
var elemClickHandler = function (e) {
e.stopPropagation();
};
var docClickHandler = function () {
scope.$apply(attr.clickAnywhereButHere);
};
elem.on('click', elemClickHandler);
$document.on('click', docClickHandler);
// teardown the event handlers when the scope is destroyed.
scope.$on('$destroy', function () {
elem.off('click', elemClickHandler);
$document.off('click', docClickHandler);
});
}
};
Then in your html element
<div class="mypopup" click-anywhere-but-here="function(){ alert('click out popup event')}"></div>

Related

Angular JS watch factory variable

I have a factory variable which is shared by two directives. One directives changes it and I need it to update the value in other directive as well.
This is my factory code
commonApp.factory('setSmsMessage', [function () {
var factoryObj = {
data: {
isSms: false
},
setSms: function () {
factoryObj.data.isSms = true;
},
reset: function () {
factoryObj.data.isSms = false;
}
};
return factoryObj;
}]);
This is my one directive
commonApp.directive('osSendMessage', ['setSmsMessage',
function (setSmsMessage) {
return {
restrict: 'A',
scope: {
sent: '='
},
link: function (scope, element, attrs) {
},
controller: function ($scope) {
$scope.setSmsMessage = setSmsMessage.data;
$scope.$watch('setSmsMessage.isSms', function (newValue, oldValue, scope) {
console.log(setSmsMessage.data.isSms);
}, true);
},
templateUrl: "/Static/js/AngularApps/MessageCenter/sendmessage/Templates/sendmessages.html"
};
}]);
This is my other directive which sets the variable
commonApp.directive('osMessageCenterMenu', ['setSmsMessage', function (setSmsMessage) {
return {
restrict: 'A',
scope: {
messages: "="
},
controller: function ($scope) {
},
link: function (scope) {
// opening sms
$("#toggleSendSmsMessage").click(function () {
scope.openSendSms();
});
scope.openSendSms = function () {
console.log("from menu: " + setSmsMessage.data.isSms);
setSmsMessage.setSms();
console.log("from menu: " + setSmsMessage.data.isSms);
$("#SendMessageForm").toggle();
}
// end here
,
templateUrl: "/Static/js/AngularApps/MessageCenter/Templates/messageCenterMenu.html"
};
}]);
But the value is not updated in the other controller which is listening to it
A better way would be to store the isSms property in a global object like so:
commonApp.factory('setSmsMessage', [function ()
{
var factoryObj = {
data: {
isSms: false
},
setSms: function ()
{
factoryObj.data.isSms = true;
},
reset: function ()
{
factoryObj.data.isSms = false;
}
};
return factoryObj;
}]);
Now in your controller link the $scope to the factories global object which holds the isSms property.
// Link setSmsMessage to the factories data object
$scope.setSmsMessage = setSmsMessage.data;
// Now call the setSms() function. The $scope.setSmsMessage will be updated after the call.
setSmsMessage.setSms();
// You can now watch for changes in the $scope like so
$scope.$watch('setSmsMessage.isSms', function (newValue, oldValue, scope) {
console.log(setSmsMessage.data.isSms);
}, true);
Working demo
(function() {
var commonApp = angular.module("app", []);
commonApp.factory('setSmsMessage', [function ()
{
var factoryObj = {
data: {
isSms: false
},
setSms: function ()
{
factoryObj.data.isSms = true;
},
reset: function ()
{
factoryObj.data.isSms = false;
}
};
return factoryObj;
}]);
commonApp.controller("smsController", function($scope, setSmsMessage) {
// Link setSmsMessage to the factories data object
$scope.setSmsMessage = setSmsMessage.data;
// Now call the setSms() function. The $scope.setSmsMessage will be updated after the call.
setSmsMessage.setSms();
$scope.reset = function()
{
setSmsMessage.reset();
}
$scope.$watch('setSmsMessage.isSms', function (newValue, oldValue, scope) {
console.log(setSmsMessage.data.isSms);
}, true);
});
commonApp.directive('osMessageCenterMenu', ['setSmsMessage', function (setSmsMessage)
{
return {
restrict: 'A',
scope: {
messages: "="
},
controller: function ($scope)
{
},
link: function (scope)
{
console.log(scope);
// opening sms
$("#toggleSendSmsMessage").click(function ()
{
scope.openSendSms();
});
scope.openSendSms = function ()
{
console.log("from menu: " + setSmsMessage.data.isSms);
setSmsMessage.setSms();
console.log("from menu: " + setSmsMessage.data.isSms);
$("#SendMessageForm").toggle();
}
}
}
}]);
})()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="smsController">
<div os-message-center-menu>
<button id="toggleSendSmsMessage">reset message</button>
</div>
</div>
</div>
you can also work with $rootScope in your factory and emit an event with custom data and then subscribe to the event in all your controllers
Also, try naming your factory based on functionality, for obvious
reasons.
Following is what am trying to say :-
(function() {
angular
.module("myApp", [])
.factory('smsMessage', ['$rootScope', function($rootScope) {
var factoryObj = {
data: {
isSms: false
},
setSms: function() {
factoryObj.data.isSms = true;
$rootScope.$emit('SET', {isSms : true});
},
reSet: function() {
factoryObj.data.isSms = false;
$rootScope.$emit('RE-SET', {isSms : false});
}
};
return factoryObj;
}])
.controller("controllerOne", function($scope, $rootScope, smsMessage) {
$scope.setSmsMessage = smsMessage.data;
$scope.set = function(){
smsMessage.setSms();
}
$scope.reset = function(){
smsMessage.reSet();
}
$rootScope.$on('SET', function(event, data) {
alert('SET in controllerOne');
$scope.setSmsMessage = data.isSms;
});
$rootScope.$on('RE-SET', function(event, data) {
alert('RE-SET in controllerOne');
$scope.setSmsMessage = data.isSms;
});
})
.controller("controllerTwo", function($scope, $rootScope, smsMessage) {
$scope.setSmsMessage = smsMessage.data;
$scope.set = function(){
smsMessage.setSms();
}
$scope.reset = function(){
smsMessage.reSet();
}
$rootScope.$on('SET', function(event, data) {
alert('SET in controllerTwo');
$scope.setSmsMessage = data.isSms;
});
$rootScope.$on('RE-SET', function(event, data) {
alert('RE-SET in controllerTwo');
$scope.setSmsMessage = data.isSms;
});
});
})()
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="controllerOne">
<label>Controller One</label>
<button ng-click="set()">SET</button>
<button ng-click="reset()">RE-SET</button>
</div>
<div ng-controller="controllerTwo">
<label>Controller Two</label>
<button ng-click="set()">SET</button>
<button ng-click="reset()">RE-SET</button>
</div>
</div>

$locationChangeStart event hitting twice when changing the location

I am triggering a confirm modal directive popup when the form is dirty and i am changing the location.
angular.module("top.app.controllers").directive('confirmOnExit', ['$location', 'ConfirmModal', '$timeout',function (location, ConfirmModal, $timeout) {
return {
restrict: 'A',
link: function ($scope, element, attrs) {
$scope.$evalAsync(function () {
var unbindChangeSuccess = $scope.$on('$locationChangeStart', function (event, next, current, e) {
$scope.DirtyForm = ($scope.componentAddForm.$dirty ? $scope.componentAddForm.$dirty : $scope.resourceForm.$dirty)
if ($scope.DirtyForm) {
event.preventDefault();
ConfirmModal.show({
okButtonCaption: "OK",
cancelButtonCaption: "Cancel",
title: "Pending Changes",
text: "Any unsaved data to this record will be lost. Click ‘Continue’ to proceed with this action."
}).then(function () {
event.preventDefault();
$timeout(function () {
window.location = next;
$scope.$apply()
});
})
} else {
};
});
})
}
};
}]);

how to add localization in ionic popup

i had completed ionic project. i would like to change lanaguages in this code. project title, place holder , button it had changed but popup was doesn't changed. i used this code in controller and language change file.
farmer-ctrl.js :
function showPopup () {
$scope.data = {};
var myPopup = $ionicPopup.show({
template: '<input type="text" ng-model="data.category">',
title: '{{"farmers_message" | translate}}', //'Enter CoconutType',
scope: $scope,
buttons: [
{ text: 'Cancel' },
{
text: '<b>{{"save_message" | translate}}</b>',
type: 'button-positive',
onTap: function (e) {
if (!$scope.data.category) {
//don't allow the user to close unless he enters producttype
e.preventDefault();
} else {
$log.log('yes clicked: ', $scope.data.category);
addProductType();
return $scope.data.category;
}
}
},
]
});
myPopup.then(function (res) {
$log.log('Tapped!', res);
});
}
i had founded by adding translate.instant
function showPopup () {
$scope.data = {};
var myPopup = $ionicPopup.show({
template: '<input type="text" ng-model="data.category">',
// title: 'Enter CoconutType',
title: $translate.instant('{{"farmers_message" | translate}}'),
scope: $scope,
buttons: [
{ text: 'Cancel' },
{
text: $translate.instant('{{"save_message" | translate}}'),
type: 'button-positive',
onTap: function (e) {
if (!$scope.data.category) {
//don't allow the user to close unless he enters producttype
e.preventDefault();
} else {
$log.log('yes clicked: ', $scope.data.category);
addProductType();
return $scope.data.category;
}
}
},
]
});
myPopup.then(function (res) {
$log.log('Tapped!', res);
});
}
To add localization in popup you need something like this:
var alertPopup = $ionicPopup.alert({
title: $translate.instant('networkerror'),
template: '<div><p translate="onlinemessagepois"></p></div>'
});
where networkerror and onlinemessagepois exist in your local js files. (Example: "networkerror":"sometext","onlinemessagepois":"someothertext" )
Note: you have to inject $translate in your controller.

How to bind events in angular directive

I am new to angular and having problem to bind an click event to my directive.
I have an ul-list with a links in each li. When I click a link I want to do a service call that adds or removes the clicked items ID and refresh the list.
When refreshed, each list items will show if an id is "marked" or not.
Can anyone help me?
html view:
<a href="#" class="showbooklist" qtip="12568">
<img src="image.png">
</a>
Directive:
listControllers.directive('qtip', ['boklistorservice', function (boklistorservice) {
return {
restrict: 'A',
controller: ["$scope", "$attrs","$element", "boklistorservice", function ($scope, $attrs,$element, boklistorservice) {
boklistorservice.getdata().then(function (data) { //serice call to gett data
$scope.booklist = data;
$element.qtip({ //use the jquery.tip2.js tooltip plugin
content: {
text: getcurrentbooklist($attrs.qtip, data.barnenskrypin.booklistor)
},
position: {
my: 'bottom center',
at: 'top center'
},
hide: {
fixed: true,
delay: 300
}
});
})
}]
};
}]);
//function returns a string. An ul to show in the toolbox
var getcurrentbooklist = function (bookid, arr) {
var rettext = "<ul>";
$.each(arr, function (item, val) {
item;
var inlist = false;
$.each(val.bookitems, function (i, v) {
if (v.bookid == bookid) {
inlist = true;
return false;
} else {
inlist = false;
}
});
if (inlist) {
rettext += "<li><a (NEED A CLICK EVENT HERE and pass bookid) > " + val.booklistnamn + "-- MARK </a></li>";
} else {
rettext += "<li><a (NEED A CLICK EVENT HERE and pass bookid) >" + val.booklistnamn + "--</a></li>";
}
});
rettext += "</ul>";
return rettext;
};
Use the link function of a directive (code untested):
listControllers.directive('qtip', ['boklistorservice', function (boklistorservice) {
return {
restrict: 'A',
link: function ($scope, element, attrs) {
element.bind('click', function () {
//Do your work here
});
},
controller: ["$scope", "$attrs","$element", "boklistorservice", function ($scope, $attrs,$element, boklistorservice) {
boklistorservice.getdata().then(function (data) { //serice call to gett data
$scope.booklist = data;
$element.qtip({ //use the jquery.tip2.js tooltip plugin
content: {
text: getcurrentbooklist($attrs.qtip, data.barnenskrypin.booklistor)
},
position: {
my: 'bottom center',
at: 'top center'
},
hide: {
fixed: true,
delay: 300
}
});
})
}]
};
}]);
jquery.tip2 adds the html to body so you need to find the content in body and add the click event
$element.qtip();
angular.element(document.body).find('[qtip container id or class or element] a').bind('click', function () {
//Do your work here
});

Can angular's ngTouch library be used to detect a long click (touch/hold/release in place) event?

My AngularJS app needs to be able to detect both the start and stop of a touch event (without swiping). For example, I need to execute some logic when the touch begins (user presses down their finger and holds), and then execute different logic when the same touch ends (user removes their finger). I am looking at implementing ngTouch for this task, but the documentation for the ngTouch.ngClick directive only mentions firing the event on tap. The ngTouch.$swipe service can detect start and stop of the touch event, but only if the user actually swiped (moved their finger horizontally or vertically) while touching. Anyone have any ideas? Will I need to just write my own directive?
Update 11/25/14:
The monospaced angular-hammer library is outdated right now, so the Hammer.js team recommend to use the ryan mullins version, which is built over hammer v2.0+.
I dug into ngTouch and from what I can tell it has no support for anything other than tap and swipe (as of the time of this writing, version 1.2.0). I opted to go with a more mature multi-touch library (hammer.js) and a well tested and maintained angular module (angular-hammer) which exposes all of hammer.js's multi-touch features as attribute directives.
https://github.com/monospaced/angular-hammer
It is a good implementation:
// pressableElement: pressable-element
.directive('pressableElement', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, $elm, $attrs) {
$elm.bind('mousedown', function (evt) {
$scope.longPress = true;
$scope.click = true;
// onLongPress: on-long-press
$timeout(function () {
$scope.click = false;
if ($scope.longPress && $attrs.onLongPress) {
$scope.$apply(function () {
$scope.$eval($attrs.onLongPress, { $event: evt });
});
}
}, $attrs.timeOut || 600); // timeOut: time-out
// onTouch: on-touch
if ($attrs.onTouch) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouch, { $event: evt });
});
}
});
$elm.bind('mouseup', function (evt) {
$scope.longPress = false;
// onTouchEnd: on-touch-end
if ($attrs.onTouchEnd) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouchEnd, { $event: evt });
});
}
// onClick: on-click
if ($scope.click && $attrs.onClick) {
$scope.$apply(function () {
$scope.$eval($attrs.onClick, { $event: evt });
});
}
});
}
};
})
Usage example:
<div pressable-element
ng-repeat="item in list"
on-long-press="itemOnLongPress(item.id)"
on-touch="itemOnTouch(item.id)"
on-touch-end="itemOnTouchEnd(item.id)"
on-click="itemOnClick(item.id)"
time-out="600"
>{{item}}</div>
var app = angular.module('pressableTest', [])
.controller('MyCtrl', function($scope) {
$scope.result = '-';
$scope.list = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
{ id: 7 }
];
$scope.itemOnLongPress = function (id) { $scope.result = 'itemOnLongPress: ' + id; };
$scope.itemOnTouch = function (id) { $scope.result = 'itemOnTouch: ' + id; };
$scope.itemOnTouchEnd = function (id) { $scope.result = 'itemOnTouchEnd: ' + id; };
$scope.itemOnClick = function (id) { $scope.result = 'itemOnClick: ' + id; };
})
.directive('pressableElement', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, $elm, $attrs) {
$elm.bind('mousedown', function (evt) {
$scope.longPress = true;
$scope.click = true;
$scope._pressed = null;
// onLongPress: on-long-press
$scope._pressed = $timeout(function () {
$scope.click = false;
if ($scope.longPress && $attrs.onLongPress) {
$scope.$apply(function () {
$scope.$eval($attrs.onLongPress, { $event: evt });
});
}
}, $attrs.timeOut || 600); // timeOut: time-out
// onTouch: on-touch
if ($attrs.onTouch) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouch, { $event: evt });
});
}
});
$elm.bind('mouseup', function (evt) {
$scope.longPress = false;
$timeout.cancel($scope._pressed);
// onTouchEnd: on-touch-end
if ($attrs.onTouchEnd) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouchEnd, { $event: evt });
});
}
// onClick: on-click
if ($scope.click && $attrs.onClick) {
$scope.$apply(function () {
$scope.$eval($attrs.onClick, { $event: evt });
});
}
});
}
};
})
li {
cursor: pointer;
margin: 0 0 5px 0;
background: #FFAAAA;
}
<div ng-app="pressableTest">
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in list"
pressable-element
on-long-press="itemOnLongPress(item.id)"
on-touch="itemOnTouch(item.id)"
on-touch-end="itemOnTouchEnd(item.id)"
on-click="itemOnClick(item.id)"
time-out="600"
>{{item.id}}</li>
</ul>
<h3>{{result}}</h3>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
Based on: https://gist.github.com/BobNisco/9885852
The monospaced angular-hammer library is outdated right now, so the Hammer.js team recommend to use the ryan mullins version, which is built over hammer v2.0+.

Resources