onsen dialog have limited access to parent scope - angularjs

I'm looking for some help on using onsen-ui's dialog component. It seems to be a scope issue.
In my HTML file, I have a dialog template looks like this.
<ons-template id="report.html">
<ons-dialog var="dlg" cancelable>
<h1>{{clicked.name}}</h1>
<ons-button onclick="clickButton()">Click</ons-button>
</ons-dialog>
</ons-template>
And in my controller, I have
$scope.clickButton = function(){
dlg.hide();
}
$scope.dialogs = {};
$scope.show = function(dlg) {
$scope.clicked = {'name':"bar"};
if (!$scope.dialogs[dlg]) {
ons.createDialog(dlg, {parentScope: $scope}).then(function(dialog) {
$scope.dialogs[dlg] = dialog;
dialog.show();
});
} else {
$scope.dialogs[dlg].show();
}
}
The weird part is that I can access "clicked" in the dialog scope, but not "reportButton", they are in the same scope, or at least I can tell.
Here is the codepen link
Thanks in advance!

To call the function from controller scope, you should be ng-click instead of onclick.
<ons-button ng-click="reportButton()">click</ons-button>
Working Codepen

Related

ng-click not working on a programmatically added buttons

I'm trying to add some buttons (ons-button) dynamically. The buttons appear as expected but the ng-click related to them never gets fired. It seems to be a problem with my understanding of how DOM manipulation works under AngularJS.
I have tried to read related questions, but most of them are trying to use directives, so I would like to use the simple way here.
Here is the code:
var module = angular.module("my-app", ["onsen"]);
module.controller("ListenButtonController", [
"$http",
"$scope",
function($http, $scope) {
var myList = [];
$scope.onButtonClick = function(message){
alert('Button clicked, with the message '+message);
}
$scope.onAddButtons = function(newList){
myList = [...newList];
}
}
}
]);
Here is the HTML:
<ons-page ng-controller="ListenButtonController">
<ons-button modifier="large" ng-click="onAddButtons(['a','b','c'])">
Click to test
</ons-button>
<ons-button ng-repeat="element in myList" ng-click="onButtonClick(element)"></ons-button>
</ons-page>

How to hide popover in onsen ui

I have been following Drop down option menu using onsen UI, but I want to cancel the popover when tapping on it. Any idea.
Usually, you can just hide it with popover.hide(), but it seems there is a bug when you try to use again the same controller with a popover containing a list (the browser gets stuck and the CodePen sample get bugged). That's why you need to create another controller to hide the popover and a service to share the popover between the two controllers (Here you can find a working CodePen).
var app = ons.bootstrap();
app.controller('DropdownController', function($scope, myService) {
ons.createPopover('popover.html').then(function(popover) {
$scope.popover = popover;
myService.setPopover($scope.popover);
});
});
app.controller('MyController', function($scope, myService) {
$scope.destroyPopover = function() {
$scope.popover = myService.getPopover();
$scope.popover.hide();
}
});
app.service("myService", function(){
var sharedPopover
var setPopover = function(pop){
sharedPopover = pop;
};
var getPopover = function(){
return sharedPopover;
};
return {
setPopover: setPopover,
getPopover: getPopover,
};
});
After, just add the controller in the new popover.html template, and the ng-click="destroyPopover()" directive to the ons-list-item. Doing that, the popover will be hidden every time you click the list element.
<ons-template id="popover.html" >
<ons-popover direction="down" cancelable >
<ons-list ng-controller="MyController">
<ons-list-item modifier="tappable" ng-click="hidePopover()">Option 1</ons-list-item>
<ons-list-item modifier="tappable" ng-click="hidePopover()">Option 2</ons-list-item>
<ons-list-item modifier="tappable" ng-click="hidePopover()">Option 3</ons-list-item>
</ons-list>
</ons-popover>
</ons-template>
EDIT
There is another way to hide the popover without using an AngularJS Service.
Since Onsen UI 1.3 release it's possible to pass scope for dialogs and popover, when creating them with ons.createDialog(), ons.createPopover() and ons.createAlertDialog(). (source).
When creating a dialog the following syntax can be used:
ons.createDialog('dialog.html', {parentScope: $scope}).then(function(dialog) {
$scope.dialog = dialog;
});
and use
<ons-list-item modifier="tappable" ng-click="popover.hide()">Option 1</ons-list-item>
You can find a working CodePen example HERE.

reusable modal windows design patterns angularJS

I have been trying to create a modal windows that are re-usable with angularJS.
While I am googling I come to know that re-usable modals are created by using
custom directives.
services.
I'm in a confusion which method to follow.
What is the most customized method for creating modal windows in angularJS? and any resources on how to create re-usable modal windows (design patterns for modal windows) in angularJS
Note: Please suggest solutions without angular-bootstrap-ui or bootstrap.
Update:
I am trying to develop a similar kind of screen.
when the user clicks on "select Bus" link a modal window will be displayed.
Title, Content of the modal window is based on the corresponding hyper link.
I've already done this screen by using custom directives with the help of
How to Create a Simple Modal Dialog Directive in Angular.js
But what I am going to rewrite it as a reusable module or directive.
So suggest some design patterns to create re usable custom modal dialog windows using angularJS
Please check the following link for re-usable windows in angular.
That may resolve your issues.
http://www.dwmkerr.com/the-only-angularjs-modal-service-youll-ever-need/
A fairly simple one is ng-modal (https://github.com/adamalbrecht/ngModal), it is a directive, meaning it is highly re-usable. Services are do-able as well, but they are meant to get/set/process data rather than display HTML; hence directives are the way to go.
I've used ng-modal and adding just a little code to it went a long way to make it super-reusable. You can place it in it's own controller and have it always injected so that you can open the modal and show a message or some html.
HTML:
<div ng-controller="modalCtrl">
<modal-dialog show='dialogShown' dialog-title='titleToUse' height='400px' width='75%'>
<p ng-bind="messageToShow"> </p>
<div ng-bind-html="someHTML"></div>
</modal-dialog>
</div>
JS:
myApp.controller('modalCtrl', function($scope){
$scope.titleToUse = "Modal Title";
$scope.messageToShow = "Testing Message"; // default message
$scope.someHTML = "<div>Whoa! A Div!</div>";
$scope.$on('changeMessageEvent', function($event, message){ // listens for change message event and sets new message
$scope.messageToShow = message;
});
});
myApp.controller('someOtherController', function($scope, $rootScope){ // import rootScope
var messageToSendToModal = "New Message!";
$rootScope.$broadcast('changeMessageEvent', messageToSendToModal );
});
Update:
If you want dynamic template and controllers, that is easily to do with ng-modal, you just have to use ng-include:
<div ng-controller="modalCtrl">
<modal-dialog show='dialogShown' dialog-title='titleToUse' height='400px' width='75%'>
<p ng-bind="messageToShow"> </p>
<div ng-bind-html="someHTML"></div>
<!-- some dynamic template -->
<ng-include src="pathToTemplate"></ng-include>
</modal-dialog>
</div>
where in modalCtrl you have
$scope.pathToTemplate = "/path/to/template.html";
that template can contain a controller and can be switched out dynamically via variables.
If anyone is looking for another example I just had a crack at creating a custom modal service and directive myself, with them you can add modals to views like this:
<button ng-click="vm.openModal('custom-modal-1')">Open Modal 1</button>
<modal id="custom-modal-1">
<div class="modal">
<div class="modal-body">
<h1>A Custom Modal!</h1>
<p>
Home page text: <input type="text" ng-model="vm.bodyText" />
</p>
<button ng-click="vm.closeModal('custom-modal-1');">Close</button>
</div>
</div>
<div class="modal-background"></div>
</modal>
Here's the controller that opens and closes the modal:
(function () {
'use strict';
angular
.module('app')
.controller('Home.IndexController', Controller);
function Controller(ModalService) {
var vm = this;
vm.openModal = openModal;
vm.closeModal = closeModal;
initController();
function initController() {
vm.bodyText = 'This text can be updated in modal 1';
}
function openModal(id){
ModalService.Open(id);
}
function closeModal(id){
ModalService.Close(id);
}
}
})();
This is the custom modal service:
(function () {
'use strict';
angular
.module('app')
.factory('ModalService', Service);
function Service() {
var modals = []; // array of modals on the page
var service = {};
service.Add = Add;
service.Remove = Remove;
service.Open = Open;
service.Close = Close;
return service;
function Add(modal) {
// add modal to array of active modals
modals.push(modal);
}
function Remove(id) {
// remove modal from array of active modals
var modalToRemove = _.findWhere(modals, { id: id });
modals = _.without(modals, modalToRemove);
}
function Open(id) {
// open modal specified by id
var modal = _.findWhere(modals, { id: id });
modal.open();
}
function Close(id) {
// close modal specified by id
var modal = _.findWhere(modals, { id: id });
modal.close();
}
}
})();
And this is the custom modal directive:
(function () {
'use strict';
angular
.module('app')
.directive('modal', Directive);
function Directive(ModalService) {
return {
link: function (scope, element, attrs) {
// ensure id attribute exists
if (!attrs.id) {
console.error('modal must have an id');
return;
}
// move element to bottom of page (just before </body>) so it can be displayed above everything else
element.appendTo('body');
// close modal on background click
element.on('click', function (e) {
var target = $(e.target);
if (!target.closest('.modal-body').length) {
scope.$evalAsync(Close);
}
});
// add self (this modal instance) to the modal service so it's accessible from controllers
var modal = {
id: attrs.id,
open: Open,
close: Close
};
ModalService.Add(modal);
// remove self from modal service when directive is destroyed
scope.$on('$destroy', function() {
ModalService.Remove(attrs.id);
element.remove();
});
// open modal
function Open() {
element.show();
$('body').addClass('modal-open');
}
// close modal
function Close() {
element.hide();
$('body').removeClass('modal-open');
}
}
};
}
})();
For more info you can check out this blog post

disable swipe in ionic slidebox

In ionic we have slideBox.I want to disable swipe .I want it to slide on button click.How can i do it?
I have tried $ionicSlideBoxDelegate.enableSlide(false) in my controller but it is not working.
According to this link http://forum.ionicframework.com/t/ionicslideboxdelegate-disable-all-swiping/6391 i have to disable in the scope of the slidebox but how to access the scope of the element and apply it?
The proper place to do it is in ng-init
<ion-slide-box ng-init="lockSlide()">
and have the respective function in your controller
.controller('sliders', function($scope, $ionicSlideBoxDelegate) {
$scope.lockSlide = function () {
$ionicSlideBoxDelegate.enableSlide( false );
}
}
In your html file put active-slide="slidestop($index)"
<ion-slide-box active-slide="slidestop($index)">
</ion-slide-box>
And in Controller class that function "slidestop"
$scope.slidestop = function(index) {
$ionicSlideBoxDelegate.enableSlide(false);
}
Your issue is probably that the slidebox needs to be rendered before you can disable sliding. So in your controller, use a timeout:
$timeout(function(){
$ionicSlideBoxDelegate.enableSlide(0);
},0);
In your html add
<ion-slide-box active-slide="slidestop" does-continue="false">
And in your controller add
$timeout(function(){
$ionicSlideBoxDelegate.enableSlide(false);
},0);

angular-maps not showing window inside marker

I'm trying my best to show a window when clicking on a marker in angular-google-maps. Pretty much what is done here http://angular-google-maps.org/demo.
This is the function which generates the markers - it's called from a rest service, and each marker object can be viewed in coordinates.json:
var generateMarkers = function(markers) {
angular.forEach(markers, function(marker) {
marker.onClick = function() {
console.log('on click - opening window');
marker.showWindow = true;
$scope.$apply();
}
marker.closeClick = function() {
console.log('close click - hiding window');
marker.showWindow = false;
$scope.$apply();
}
});
$scope.map.randomMarkers = markers;
};
This is the code which declares the marker (no controller nesting and one $scope ). The window will inherit the
<google-map center="map.center" zoom="map.zoom" draggable="true"
bounds="map.bounds" control="map.control">
<markers models="map.randomMarkers" coords="'self'"
icon="'icon'"
click="'onClick'">
<windows
show="'showWindow'"
coords="'self'"
closeClick="'closeClick'" ng-cloak="">
<div>
Window with additional information
</div>
</windows>
</markers>
</google-map>
This is either a bug in angular-google-maps or I'm doing something wrong (which is likely)
I've created a plunkr, which demonstrates the behavior --> http://plnkr.co/edit/z1TdYlYbhSYWZb7n3L4M?p=preview
Please tell me what you think.
For posterity sake, this was answered over at https://github.com/nlaplante/angular-google-maps/issues/497 .
Basically, initialize to an empty array the property that coords is bound to, so that the reference gets updated correctly in angular.
This can be seen working here http://plnkr.co/edit/nbX0BIxNhxFrpzpruRWb?p=preview.

Resources