for my ionic v1 app I need to add one header menu (like as bootstrap menu) in right corner. When I click this button, i need to show menu with same ng-click event. For graphical requirement I need a menu and no side menu.
Found $ionicPopover, and I think that is my solution.
My problem is about menu function. My idea is use a html template for all menu, and put popover function samewhere accessibile for all my app. Is possibile?
Found only example where for every controller I need to implement popover function.
For example this is a simple controller. I need to define popover function globally for all my project. Same for popover definition. Is possible? Thanks.
.controller('DashCtrl', function($scope, $ionicLoading, $ionicPopover) {
// .fromTemplate() method
var template = '<ion-popover-view>' + '<ion-header-bar>' +
'<h1 class = "title">Popover Title</h1>' +
'</ion-header-bar>'+ '<ion-content>' +
'Popover Content!' + '</ion-content>' + '</ion-popover-view>';
$scope.popover = $ionicPopover.fromTemplate(template, {
scope: $scope
});
$scope.openPopover = function($event) {
$scope.popover.show($event);
};
$scope.closePopover = function() {
$scope.popover.hide();
};
//Cleanup the popover when we're done with it!
$scope.$on('$destroy', function() {
$scope.popover.remove();
});
// Execute action on hide popover
$scope.$on('popover.hidden', function() {
// Execute action
});
// Execute action on remove popover
$scope.$on('popover.removed', function() {
// Execute action
});
})
Like stated in my comment, you should create a root-template view with a separate Controller that holds the logic shared by all views. Take the following setup as an example:
The "Root Template": (Contains the Menu Button)
<!-- templates/root.html -->
<div>
<ion-nav-bar class="bar-positive">
<ion-nav-buttons side="right">
<button class="button icon ion-android-more-vertical" ng-click="showMenu($event)"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="content"></ion-nav-view>
</div>
Dash Templates:
<!-- views/dash.html -->
<ion-view view-title="Dash View">
<ion-content>
Hello World!
</ion-content>
</ion-view>
The states:
$stateProvider
.state('root', {
url: '/root',
abstract: true,
templateUrl: 'templates/root.html',
controller: 'RootCtrl'
})
.state('root.dash', {
url: '/sub',
views: {
'content': {
controller: 'DashCtrl',
templateUrl: 'views/dash.html'
}
}
})
In the DashCtrl you will put your logic to handdle the popup. Thus this controller has to implement the showMenu($event) function.
If you really need a template for your popover, you can define the template in either in the html of templates/root.html or in the code of **RootController.js".
Finally, I create single function in single controller, with a common menu header. Thanks.
I know the OP resolved his issue but did it in a different way than was originally asked. The OQ was how to do a global popover...the accepted answer was to do controller view instead.
But to do a global popover, this is how I did it. I am certain some might object to this because of the dependency of $rootScope but it is a working solution:
In app.js:
var popoverPromise = $ionicPopover.fromTemplateUrl('templates/windowPopup.html', {
scope: $rootScope,
focusFirstInput:false
});
popoverPromise.then(function(popover) {
$rootScope.msgPopover = popover;
});
$rootScope.globalPopover = function(tpt,tps,tpm,tps1,tpm1,tpa,tpc) {
popoverPromise.then(function(popover) {
$rootScope.popInfo.title = tpt ;
$rootScope.popInfo.sub = tps ;
$rootScope.popInfo.msg = tpm ;
$rootScope.popInfo.sub1 = tps1;
$rootScope.popInfo.msg1 = tpm1 ;
$rootScope.popInfo.action = tpa ;
$rootScope.popInfo.color1 = tpc ;
$popover.show();
}) ;
}
$rootScope.globalClosePopover = function() {
$rootScope.msgPopover.hide();
}
And then from all the various controllers where you need it, inject $rootScope:
$rootScope.globalPopover(a,b,c,d,e,f,g) ;
An alternative to the above, if you don't need it everywhere - like in your app in init/register/startup controllers, is to put all this in your Tabs-Controller.
Related
all!
I'm making an angular application and want to implement a simple modal window popup, that will allow users to "construct" a URL.
My page looks like this:
Here's the HTML of the URL button (third in row) that is to trigger my button.
<button class="btn btn-secondary" ng-click="vm.showUrlModal()" id="button-url-to-modal" type="button" title="Hyperlink <a> Ctrl+L"><img src="/images/url.png" height="18px"/></button>
The controller that handles the page looks like this:
(function() {
function postchallengeController($uibModal, newChallengeData) {
var vm = this;
vm.message = "Post a challenge!";
vm.showUrlModal = function() {
$uibModal.open({
templateUrl: '/url_modal/url_modal.view.html',
controller: 'url_modal',
controllerAs: 'vm',
})
}
postchallengeController.$inject = ['$uibModal', 'newChallengeData'];
/* global angular */
angular
.module('stackunderflow')
.controller('postchallengeController', postchallengeController);
})();
And the referenced url_modal controller:
(function() {
function url_modal($uibModalInstance) {
var vm = this;
vm.modal = {
cancel: function() {
$uibModalInstance.close();
}
};
}
url_modal.$inject = ['$uibModalInstance'];
/* global angular */
angular
.module('stackunderflow')
.controller('url_modal', url_modal);
})();
In the referenced document (/url_modal/url_modal.view.html) is a simple Hello World, that should be displayed when I open the modal - however, when I do so, the page opens a modal with the current content overlayed on top of it.
See here :
What could I be doing wrong?
Thank you!
EDIT: I do have both controllers referenced in my index.html and my module does contain ['ui.bootstrap']
The error might be hidden in the reference of the html file.
Make sure that the parent directory of the /url_modal/ directory is set as the root folder you set with express.static function call.
I am having mdDialog in one controller to show details from another controller.when I click the close button, it does not close.
I used both :
$mdDialog.hide() and $mdDialog.cancel()
re-check all these:
correct usage of $mdDialog API:
$mdDialo.show({
controller:function($scope,$mdDialog){
$scope.close = function(){$mdDialog.hide();}
},
templateUrl:'some-template.dialog.html'
})
correct link from controller to template.
i.e. if you are using $scope.close = function(){ ... }, then your template should look like : <md-button ng-click=close()>close</md-button>
and if you are using controller:
this.close = function(){...}
then you need to add a controllerAs in your $mdDialog.show() config object:
controllerAs:'$ctrl'
and in your template:
<md-button ng-click=$ctrl.close()></md-button>
I need to show a confirmation box on different pages. So i have decided to create a custom directive for performing this task. I have a html template for confirmation box.There are two buttons and some text in this template. One button is for cancelling the dialog box and one for submitting it. So the functionality will be different for each page when we click on submit button. I have couple of questions regarding this issue.
How to create this kind of directive to show a dialog box on some condition?
How to pass text from my controller to this template?
How to override the "Submit" button functionality.
I had similar requirement where I wanted a custom modal pop-up to alert the user to continue with his actions such as delete, modify etc..,
So I wrote a custom directive. Below is the code.
(function(){
'use strict';
angular.module('mainApp').directive('confirm', ['$log','$uibModal', function($log,$uibModal){
var link = function($scope,elem,attr){
elem.bind('click',function(){
var modalInstance = $uibModal.open({
animation: true,
templateUrl: 'templates/shared/_confirm_modal.html',
controller: 'confirmDirectiveCtrl',
size: 'sm'
,backdrop: 'static' //disables modal closing by click on the backdrop.
,resolve: {
requiredVerbose: function(){
var requiredVerbose = {
modalTitle : attr.modalTitle
,message : attr.message
,confirmVerbose : attr.confirmVerbose
,cancelVerbose : attr.cancelVerbose
} ;
return requiredVerbose;
}
}
});
modalInstance.result.then(function(){
$scope.confirmFn();
}, function(){
if($scope.cancelFn){
$scope.cancelFn();
}
});
});
}
return{
restrict : 'A'
,scope : {
confirmFn : '&'
,cancelFn : '&'
}
,compile : function compile(elem,attr){
if(attr.confirmType && attr.confirmType=='delete')
{
attr.modalTitle = 'Warning';
attr.confirmVerbose = 'Delete';
attr.cancelVerbose = 'No';
attr.message = 'Are you sure, you want to delete?'
}
else{
if(!attr.modalTitle){attr.modalTitle = 'Warning'}
if(!attr.confirmVerbose){attr.confirmVerbose = 'Ok'}
if(!attr.cancelVerbose){attr.cancelVerbose = 'cancel'}
if(!attr.message){attr.message = 'Are you sure?'}
}
return{
post : link
}
}
}
}]);
angular.module('mainApp').controller('confirmDirectiveCtrl', ['$scope','$uibModalInstance','requiredVerbose',
function($scope,$uibModalInstance, requiredVerbose){
$scope.modalTitle= requiredVerbose.modalTitle;
$scope.message = requiredVerbose.message;
$scope.confirmVerbose = requiredVerbose.confirmVerbose;
$scope.cancelVerbose= requiredVerbose.cancelVerbose;
$scope.ok = function(){
$uibModalInstance.close($scope.timeline);
};
$scope.cancel = function(){
$uibModalInstance.dismiss();
};
}]);
}());
To answer your questions,
This is attribute type directive. And the element on which you add this directive tag is bound to onclick function which generates the required popup.
How to pass text?
You can pass the required text through attributes. I wanted this directive to work only for two kinds of alerts and hence had only two different sets of texts. If you want custom texts everytime, you can pass them to directive through attrs.
How to override the submit functionality?
You can pass your custom submit and cancel to this directive and bind them to the popup submit and cancel functions. The above code does the same.
Edit :
HTML template and explanation:
Below is an example describing on how you can use this directive.
<i class="fa fa-trash-o"
confirm
confirm-fn="deletePlaylist($index)"
confirm-type="delete">
</i>
The above template is an trash icon. The attributes are
directive name : confirm
confirm-fn : The function that should be called after user seleting ok/submit etc..,
confirm-type : This attribute defines what type of popup you want to show. In my case, I often use 'delete' type and hence wrote the required verbose related to it. By default, I already defined the verbose(title, message, ok-button, cancel-button).
If you want your custom messages add them in the attributes. Below is one such example.
<i class="fa fa-trash-o"
confirm
confirm-fn="doingGreatFn()"
cancel-fn="justFineFn()"
modal-title="My Modal"
message="How are you doing?"
confirm-verbose="Great"
cancel-verbose="Just Fine">
</i>
I hope, this helps
You can create a directive like below to handle both submit & cancel at any page for different functionalities in any controller. I've created an isolated scope directive but you can use change it according to your need by creating child scope scope : true; or bindToController:true (controller specific)
app.directive('confirm', ['$log', '$modal' ,'$parse','$timeout','factory', function($log, $modal,$parse,$timeout,factory) {
return {
restrict: 'E',
template:'<button type="button" class="btn form-btn" '+
'ng-click="openModal()" ng-disabled="disable" >'+
'{{buttonName}}</button>',
replace: true,
transclude: false,
scope: {
name :'=name', //can set button name ..basically u can send a text
disable :'=disable' //set as an attribute in HTML to disable button
},
link: function ($scope, element, attrs) {
$scope.buttonName = $scope.name;
$scope.openModal= function() {
$scope.modal = $modal.open({
templateUrl: 'customConfirmModal.html',
scope:$scope,
persist: true,
backdrop: 'static'
});
};
$scope.cancel = function(){
$scope.modal.dismiss();
};
$scope.submit= function(){
factory.customSubmitCall($scope);//call the factory method which will call different functions depending on the need..
};
}
Create a factory to contain different functions which can be called at any controller by injecting factory.
app.factory('factory', ['$http','$rootScope','$filter',function($http,$rootScope,$filter){
factory.customSubmitCall = function ($scope){
if($rootScope.page ==1){ //check on which page you are performing action
$scope.pageOneSubmit(); //page specific function in that controller..
}else{
$scope.submit();
}
};
return factory;
}]);
In your HTML
<confirm name="Confirm" disable="disable"> </confirm>
So, for whatever reason, I am trying to create a slider, where the contents of each slide are different HTML templates. So instead of an image slider, you could say it's a HTML slider.
So in my HTML I just have this code, and the controls for the slider are also inside this HTML template:
<slide-template></slide-template>
And here is my entire slide module:
(function() {
'use strict';
angular
.module('slideCtrl', [])
.directive('slideTemplate', function() {
return {
restrict: 'E',
templateUrl: 'views/slides/slide-1.html',
replace: true,
controller: 'slideController',
controllerAs: 'slides'
}
})
.controller('slideController', function() {
var vm = this;
});
})();
I'm not sure how to move forward with this, I've tried looking around but haven't found anything that I felt I could use. Inside the controller, I would like to have an array of slide template URLs and a corresponding variable to indicate the current slide:
slideUrl = [ 'views/slides/slide-1.html', 'views/slides/slide-2.html'];
slideNum = 0;
Ideally, I would then like my directive to use these variables to determine what variable it will use for templateUrl. So by default, you can see that slideNum is 0, meaning that I want to use slide1.html or slideUrl[0]. So, my templateUrl would be something like slideUrl[slideNum]. Of course, this can't be done as the directive wouldn't be able to access that data, so I'm not sure how to do this.
The end result would be that if you clicked one of the slide navigation icons, you would be updating the slideNum variable, which would instantly change the templateUrl used.
I guess I am essentially wanting a slider which doesn't rely on some images or something like that for content, but instead is a slider of actual HTML content.
Any ideas? If I haven't explained myself well enough, please let me know.
hi I would solve it like this by creating a "main.html" template and in that:
//main.html
<div ng-if="slide == 1">
<ng-include src="'slide1.html'"/>
</div>
<div ng-if="slide == 2">
<ng-include src="'slide2.html'"/>
</div>
<div ng-if="slide == 3">
<ng-include src="'slide3.html'"/>
</div>
//controller
.controller('slideController', function() {
$scope.slide = 1
//logic to switch slides
});
for animations on the slide transitions take a look at this code pen
animations
I would suggest a main directive, where you would place the different slides on one page.
For instance, the main directive:
<div ng-include src="'slider0.html'" ng-if="slider%4==0"></div>
<div ng-include src="'slider1.html'" ng-if="slider%4==1"></div>
<div ng-include src="'slider2.html'" ng-if="slider%4==2"></div>
<div ng-include src="'slider3.html'" ng-if="slider%4==3"></div>
And then in the controller of the directive you set:
$scope.slider = 0;
// Some more logic like:
$scope.slider++;
You could move this to a link function and replace your compiled slide dynamically by adding them to the slideUrl array. This method is flexible enough to allow you to manage the slides in the controller, also you could potentially pass the slide urls to the directive through an scoped attribute.
.directive('slideTemplate', function($http, $compile, $templateCache) {
return {
restrict: 'E',
replace: true,
controller: 'slideController',
controllerAs: 'slides',
link : function(scope, el, attrs) {
// Bind active slide number to controller scope
scope.slides.num = 0;
// Declare slide urls
var slideUrl = [
'views/slides/slide-1.html',
'views/slides/slide-2.html'
];
// Load a slide and replace the directives inner html
// with the next slide.
function loadSlide(template) {
// Get the template, cache it and append to element
$http.get(template, { cache: $templateCache })
.success(function(content) {
el.replaceWith($compile(content)(scope));
}
);
}
// Progress to the next slide, this is bound to the
// controllers scope and can be called from there.
scope.slides.next = function() {
var next = scope.slides.num + 1;
var slide = slideUrl[next] ? next : slide;
scope.slides.num = slide;
loadSlide(slideUrl[slide]);
}
}
}
});
I have created a directive called modalDialog, which is basically that, a modal dialog. It uses transclude, so I can later do this in my code:
<div modal-dialog id="dialog" dialog-title="This is my Dialog">
...
here goes the content of the dialog
</div>
I want to use this directive in different places of my application, and for different purposes. The content of the dialogs will vary, naturally, so it would be very nice to have a way to pass the Controller to the directive, in the same way that I pass the dialog-title or any other parameter.
I thought about wrapping the modal-dialog in a div, with a controller set on it. Like this:
<div ng-controller="ThisInstanceController">
<div modal-dialog id="dialog" dialog-title="This is my Dialog">
...
here goes the content of the dialog
</div>
</div>
But I don't quite like it. Is there a more elegant way to do it?
Take a look at Angular-UI modals. They have a pretty elegant way of using modals. In short you can pass which controller you'd like to initialize when the modal opens.
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: ModalInstanceCtrl,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log('Modal dismissed at: ' + new Date());
});
};
The nice part as well is you can pass data with the resolve between controllers.