Create search modal directive from angularui modal - angularjs

I have an application that uses angular-ui bootstrap modal (http://angular-ui.github.io/bootstrap/#/modal) for search from a list and select one of row.
In common using of angular-ui bootstrap modal, we must create two controller (for example ModalDemoCtrl for main modal and ModalInstanceCtrl for modal window).
In second controller, we have two method:
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
that repeat in several place (when I create several search modal).
How to I create a directive (or service), that contains these two controller and create these two methods inside it.

You are wrong - there is one controller for modal window. Second one is for main page and is not related to modals at all. So if u want to have 10 buttons on page to open 10 different modals, then u will have 11 controllers.
For modals that just displays message or ask to confirm actions it is good to have service, so u can write Myservice.showModal('Are you sure?', function callbackafterok() {...}).
If u just dont like repeating $modalInstance.close - make simple directive for buttons with ng-click binding, to write:
<button closeModalWithData="" >Ok</cancel>
or just
<modalOk/> with template <button ng-click="ok()">Ok</button>...

Petr Averyanov's answer was right. I created a directive and towards the end of the documentation for Angular UI modal directive, When we create a modal window, some property adds to $scope.
One of property is $close that we can use it to close modal.
Like this:
.directive('closeModal', function() {
return {
restrict: 'E',
template: '<button ng-click="$close()">Cancel</button>'
};
})

Related

How do I dynamically create clickable keywords that display a modal (uibModal) dialog in AngularJS

I am new to AngularJS. I have been developing a site that displays a list. Each element in the list is a delivered from the server as a string. Within each element I use bars as delimeters for keywords that I'd like the user to be able to click on (i.e. this is a |keyword| in this element).
I use a controller/filter to create html to remove the delimiters and make the keywords red (using a class). So the html looks ends up looking like this:
<span ng-controller="formatForGlossaryAndCodeTextCtrl" class="ng-scope">
<span ng-bind-html="formattedLineItem" class="ng-binding">
this is a
<span class="glossaryLookup" >keyword</span> <!--here is my keyword-->
in this element
</span>
</span>
I tried having the filter also generate ng-controller=xxx and ng-click=xxx in order to stay in the angular world but that doesn't work (my keyword is not clickable when I do that).
I DO have jQuery code that binds the click event to the elements with class=glossaryLookup. It currently displays an alert when I click on the keyword.
I am at a loss as to how to get that click to display an angular modal dialog. I want it to use an angular modal dialog because there is another part of the same application that already displays an angular modal dialog and I want to be consistent
So, in short... the server delivers a string containing one or more delimited words to the browser. I'd like the angular/js/jquery code on the browser to not only highlight the delimited word(s) but allow me to click on them, look up a definition (I am not concerned about how to look up the definition, at least not yet) and display that definition in a $uibModal.
Thanks for any help.
I think I actually figured it out. I created a dummydiv and gave it an id (id=dummydiv). I "assign" a controller to that div (ng-controller=dummyCtrl).
`<div id=dummydiv ng-controller=dummyCtrl></div>`
In the jQuery code that binds the click event to my keyword I use this line of code to run the function in the dummy controller that displays the dialog:
`$(document).ready(function () {
$(document)
.on("click", ".glossaryLookup", "NEED TO LOOKUP IN GLOSSARY", function (x) {
angular.element($("#dummydiv")).scope().testclick();
})
.on("click", ".codeTextLookup", "NEED TO LOOKUP CODE TEXT", function (x) {
alert(x.data)
})
});`
BTW - the dummy controller looks like this:
`//DUMMY CONTROLLER TO TEST DYNAMIC CLICK
Hydroware_Checkbox_List_Prototype_App.controller('dummyCtrl', function ($scope, $uibModal) {
$scope.testclick = function () {
alert("I WAS CLICKED BUDDY");
var modalInstance = $uibModal.open({
templateUrl: 'line_item_help.html',
controller: "LineItemHelpDialogCtrl",
scope: $scope
});
};
});`

how to make custom directive in angular?

I am trying to make custom directive in angular .I try to add input field in my view when I click on button .In other words I am trying to make one custom directive in which when user press the button it add one input field in the browser .I think it is too easy if I am not use custom directive Mean If I use only controller then I take one array and push item in array when user click on button and button click is present on controller.
But when need to make custom directive where I will write my button click event in controller or directive
here is my code
http://play.ionic.io/app/23ec466dac1d
angular.module('app', ['ionic']).controller('appcontrl',function($scope){
$scope.data=[]
}).directive('inputbutton',function(){
return {
restrict :'E',
scope:{
data:'='
},
template:'<button>Add input</button> <div ng-repeat="d in data"><input type="text"></div>',
link:function(s,e,a){
e.bind('click',function(){
s.data.push({})
})
}
}
})
I just need to add input field when user click on button using custom directive ..could you please tell me where i am doing wrong ?
can we make button template and click event inside the directive
The reason it doesn't work is because your registering your click handler with jQuery. So when the click handler fires it is out of the scope of angular so angular does not know it needs to update its bindings.
So you have two options, the first is to tell angular in the click handler, 'yo buddy, update your bindings'. this is done using $scope.$apply
$apply docs: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply
e.bind('click',function(){
s.$apply(function() {
s.data.push({});
});
});
However angular already has built in directive for handling things like mouse clicks you can just use that and let angular do the work for you. This would be the better option.
so first in your view register a click handler on your button
<button ng-click="add()">Add input</button> <div ng-repeat="d in data"><input type="text"></div>
Then in your link simply add the add() method of your scope
s.add = function () {
s.data.push({});
}
Heres a working fiddle showing both examples. http://jsfiddle.net/3dgdrvkq/
EDIT: Also noticed a slight bug in your initial click handler. You registering a click but not specifying the button to apply it to. So if you clicked anywhere in the directive, not just the button, the handler would fire. You should be more specific when registering events manually, using ids, class names attributes etc.
The e or element property of the link function is a jqlite or full jQuery object of the entire directive. If you have jQuery included before angular it will be a full jQuery object. If not it will a jqlite object. A thinned out version of jQuery.
Here is a basic example for your logic .
var TestApp = angular.module('App', []);
// controller
TestApp.controller('mainCtrl', function mainCtrl($scope) {
$scope.data = [];
$scope.addDataItem = function () {
$scope.data.push({
someFilield: 'some value'
});
console.log('pushing value ... ');
}
});
// view
<div ng-app="App" class="container" ng-controller="mainCtrl">
<button type="button" ng-click="addDataItem()">Add an input</button>
<div ng-repeat="d in data track by $index">
<custom-directive model="d"></custom-directive>
</div>
</div>
// directive
TestApp.directive('customDirective', function customDirective() {
return {
restrict: 'E',
scope: {
model: '='
},
template: 'item -> <input type = "text" />',
link: function (scope, elem, attrs) {
console.log('scope.model', scope.model);
},
controller: function ($scope) {
// do staff here
}
}
});

confirm modal using ngDialog

I am using ngDialog in my application and I would like to create a generic confirm modal , which I can use whenever I need , the confirm message is going to be different .
My questions :
1- Is creating a directive with the ngDialog functionality a good idea and what is its design ?
2- what is the difference between confirm() and openConfirm() in ngDialog code .
Thanks in advance
Well, to answer your questions,
1 - You can create a directive for it, having a scope, say type to which you pass the confirmation type ( i.e. submit for submit confirmations, delete for delete confirmations) and the directive should render the message based on the type you specified.
2 - openConfirm() is a type of ngDialog, which can only be closed by confirming the action (unlike ngDialog.open()), so you don't have the ability here to close the dialog when clicking anywhere in theDOM. confirm() is just a method you use to close the dialog, you use this method to close the dialog and resolve the promise that was returned when opening the modal, so it can go on <button ng-click="confirm()">Confirm</button> inside your dialog.
Hope this helped you
Update
openConfirm()
Opens a dialog that by default does not close when hitting escape or clicking outside the dialog window. The function returns a promise that is either resolved or rejected depending on the way the dialog was closed.
To resolve the promise, your dialog should be like this:
With ngDialog controller
ngDialog.openConfirm({
template: '<div></div>',
controller: ['$scope', function($scope) {
// Controller logic here
}]
}).then(function (success) {
// Success logic here
}, function (error) {
// Error logic here
});
With directive controller
ngDialog.openConfirm({
template: '<div></div>',
scope: $scope, // <- ability to use the scopes from directive controller
}).then(function (success) {
// Success logic here
}, function (error) {
// Error logic here
});
You can use your directive controller as long as you pass scope: $scope inside the dialog
Here is a demo showing you how you can use type
Try switching the type in index.html from confirm to remove and see the updated content and button text in the dialog

How to hide a ionic modal that shows a list after selecting a value?

I have a ion-view that shows a list of items in a modal. I want to dismiss the modal once I select an item. I have associated the modal template with a controller using an ng-controller attribute.
How do I dismiss the modal form inside the controller where I will be getting click events ?
try like this
$scope.modal.hide();
If you are using multiple modals, give different names to scope variables..
$ionicModal.
fromTemplateUrl('example.html', {
scope: $scope,
animation: 'slide-in-up' }).
then(function(modal) {
$scope.exmapleModal = modal;
$scope.exmapleModal.show();
$scope.closeExample = function() {
$scope.exmapleModal.hide();
$scope.exmapleModal.remove();
};
});
Close the modal the same name as
$scope.closeExample();

AngularJS Directive-Controller-Service Interaction

I'm trying to design a single page pagination app that displays the different pages of a document beneath each other in the same window. It has to meet the following requirements:
A pagination toolbar where the user can click next/previous/... and submit a page to go to.
The window scrolls to the right page of the document after a page has been submitted
If the user scrolls manually, the current page should update automatically
I tried some different stuff but was never really satisfied with the result. This is how I see the solution:
The app consists of 1 factory:
DocumentFactory: Stores the current page of the document and has the following methods:
setPage(page): sets the page in a factory so different controllers/directives can use this page
broadcast(pageChanged): broadcasts an event after the page has changed so the controllers/directives can listen to this even and react approprialty
2 controllers:
PaginationCtrl[DocumentFactory]: The pagination toolbar controller, updates the page by calling the setPage(method) of the DocumentFactory and listens to the pageChange event to update it's own scope when the page changes in an other controller/directive
DocumentCtrl: The controller of the document
1 Directive:
Page[DocumentFactory]: Resembles a page in the document and has the following methods/listeners
scrollToPage(): If the currentPage equals this pages number (added to the directive as an attribute, scroll to this page)
If this page is visible and the highest in the window of all visible pages, change the current page to this page's number by calling the DocumentFactory setPage(page) method.
Is this the right approach to store the page in a service and use events for the other controllers/directives to listen to it?
Should I create a controller in the directive to listen to the event or add a $watch in the link function to watch for changes in the current page (inherited from the parent Ctrl scope)?
Should I let each directive check if it's page number equals the current page on page change or should I let the DocumentCtrl scroll to the right element?
AS you already have the methods in the controller calling the factory, what you need is to use the '&' isolate scope in the directive to call the method you want.
Create the methods in the controller
var app = angular.module('app', []);
app.controller("Ctrl", function ($scope) {
$scope.goForward = function (){
alert("call to the paginator page up service");
};
$scope.goBack = function (){
alert("call to the paginator page down service");
};
});
Then set up the '&' scope isolates in the directive:
app.directive('paginator', function (){
return{
restrict: 'E',
scope:{
forward: '&',
back: '&'
},
template: '<button ng-click="forward()">Page up</button>' +
'<button ng-click="back()">Page down</button>'
}
});
Finally add the directive to the page with your attributes as defined in the directive:
<paginator forward="goForward()" back="goBack()"></paginator>
Here's the code in Plnkr.
HTH

Resources