How to hide popover in onsen ui - angularjs

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.

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>

Having trouble with ons-list and angular ng-repeat

I declared a very simple component called betroomList:
(function () {
'use strict';
angular.module('betfriends')
.component('betroomList', {
templateUrl: 'src/home/betroomList.template.html',
controller: BetroomListController,
bindings: {
betrooms: '<'
}
});
function BetroomListController() {
var ctrl = this;
ctrl.betrooms = ['item1', 'item2', 'item3'];
}
})();
As you can see, its controller contains a table of strings. In the template HTML, I would like to create an ons-list with the content of this table. Here is what contains betroomList.template.html:
<ons-list>
<ons-list-item ng-repeat="item in $ctrl.betrooms">
<h1>{{item}}</h1>
</ons-list-item>
</ons-list>
My problem is that while it works fine in Google Chome it does not it Firefox. Indeed, in Chrome it correctly displays the list with 3 rows "item1", "item2" and "item3" but in Firefox I only have a list of one element "{{item}}".
In addition, the Firefox console contains an error:
Error: node is undefined
compositeLinkFn#http://localhost:63342/BetFriends/www/lib/angular.js:8623:13
nodeLinkFn#http://localhost:63342/BetFriends/www/lib/angular.js:9330:24
compositeLinkFn#http://localhost:63342/BetFriends/www/lib/angular.js:8620:13
publicLinkFn#http://localhost:63342/BetFriends/www/lib/angular.js:8500:30
It might be worth noting that if I replace respectively ons-list with ul and ons-list-item with li, everything works as expected.
Does anyone have an idea why this doesn't work?
Thanks a lot in advance.
You might have to take it up with Onsen UI.
The only thing I can see is that they recommend using 3 classes for the item, basically to be left, centre and right:
<ons-list-item>
<div class="left">Left</div>
<div class="center">Center</div>
<div class="right">Right</div>
</ons-list-item>
You are using a H1 tag around your {{item}}. Maybe you should try using just a div, and see what it does.

onsen dialog have limited access to parent scope

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

No instance found for handle for md-sidenav inside ng-repeat

I'm trying to create a stack of multiple, dynamically created md-sidenavs. I can push their IDs onto a stack, but can not toggle them while using ng-repeat.
Using:
app.controller('MenuCtrl', ['$scope', '$mdSidenav', function($scope, $mdSidenav) {
var stack = [];
$scope.getStack = function() {
return stack;
}
$scope.add = function(id) {
stack.push(id);
}
$scope.toggle = function(id) {
$mdSidenav(id).toggle();
}
}]);
with:
<md-button ng-click="add('test')" class="menuBtn">Add</md-button>
<md-button ng-click="toggle('test')" class="menuBtn">Toggle</md-button>
<md-sidenav class="md-sidenav-left md-whiteframe-z2" md-component-id="{{id}}" ng-repeat="id in getStack()">
{{id}}
</md-sidenav>
Clicking on the Add button produces the md-sidenav element in the doc as expected. However, the Toggle button does nothing besides produce a "No instance found for handle test" error in the console. Declaring a static md-sidenav with md-component-id="test" works fine. I'm using AngularJS 1.3.15 and Angular Material 0.8.3.
From the `Sidenav' directive source it doesn't seem to accept dynamic value for md-component-id

how can I set the position of modal dialog in angular bootstrap ui?

I'm trying to open a modal dialog at a location where the user clicked.
the modal dialog should open from a timer event, basically mouseDown start a timer, and mouseUp clear it, if enough time passed I want to open the dialog.
The dialog need to be opened at the location of the click.
I implement it all, but I do not know how to set the location of the dialog, I'm using angular bootstrap modal dialog.
any idea ?
here is a snippet of my code.
var timer = null;
var lastSceneSelectedLocation = { } ;
// handle / prepare for context menu event
$scope.mouseDown = function(event) {
lastSceneSelectedLocation.x = event.clientX;
lastSceneSelectedLocation.y = event.clientY;
timer = window.setTimeout($scope.openSceneMenu, 1000);
// tap and hold for 1 second to open menu
};
// cleanup context menu event
$scope.mouseUp = function() {
window.clearTimeout(timer);
};
$scope.ScenesContextOptions = ["Move Back", "Move Forward", "Duplicate", "Delete"];
$scope.SceneActionSelected = {};
// context menu event
$scope.openSceneMenu = function() {
console.log("in scene context menu");
var modalInstance = $modal.open({
templateUrl: 'views/SceneModalDialog.html',
scope: $scope,
windowClass: 'sceneContextMenu'
});
modalInstance.opened.then(function () {
console.log('modal opened');
});
modalInstance.result.then(function () {
console.log($scope.SceneActionSelected);
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
this maybe too late but here's how to use a angular-ui-bootstrap-popover with a custom template:
Note: you need do download a custom pull-request from angular-ui-bootstrap since the current version 0.12 doesn't support templates for popover hopefully this will be supported in 0.13.
then you can do something like this:
<button
class="btn btn-default"
popover-window-placement="top"
popover-window-trigger="click"
popover-window="templateb.html"
>
Popover With Template
</button>
notice: the directive is not popover anymore it's popover-window.
follow this issue for more information this plnkr shows a live example.
I think, bootstrap's modal is not a good idea for this taks, because you can't tell him position where to open. Maybe Popover will be more suited for your task?
A popover may satisfy your requirement.
https://angular-ui.github.io/bootstrap/#/popover
I modified the example Plunker from the Angular UI Bootstrap documentation to show how you could include a list of items to select from and then identify the selected item in your controller.
<div ng-controller="PopoverDemoCtrl">
<br/><br/><br/><br/><br/><br/>
<h4>Popover With Template</h4>
<button popover-template="dynamicPopover.templateUrl"
popover-title="{{dynamicPopover.title}}"
type="button"
class="btn btn-default">Popover With Template</button>
<script type="text/ng-template" id="myPopoverTemplate.html">
<ul>
<li ng-click="clickEvent(1)">Item 1</li>
<li ng-click="clickEvent(2)">Item 2</li>
<li ng-click="clickEvent(3)">Item 3</li>
</ul>
</script>
</div>
In your controller:
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope) {
$scope.dynamicPopover = {
templateUrl: 'myPopoverTemplate.html',
title: 'Popover With Template'
};
$scope.clickEvent = function (item) {
console.log("clickEvent: " + item);
alert("You Clicked Item: " + item);
};
});
Plunker
The Plunker is here:

Resources