I have a Modal component build in jQuery.
I want to integrate it in an Angular app that does not use jQuery, and I don't just want to have it as an external dependency. By that I mean, I don't what to leave it as a thing that can be called from controllers, but isn't a directive or service.
What I'm confused about is if it would be a good idea to have DOM logic inside an Angular service (factory, service, provider), or if I should just make a directive with & expressions? Or maybe both?
Inside controllers, I want to be able to inject Modal and call methods to show or hide the modal and set its content.
What would the proper way of doing this be?
I'm not looking for code, but rather guidance of how a "proper Angular" implementation of this would sound.
Thank you.
To answer your question about dom logic in an angular service. No, it is not a good idea, and if you really think about it, there is no need for that. What do you need:
a modal that can close/open
can execute callbacks based on whether you clicked yes or cancel
For that simple functionality you most certainly don't need any dom logic and especially not any dom logic in your services.
You can use the $modal service and do the styling yourself to make it look the same. Take a look at this plunkr:
http://plnkr.co/edit/WLJfs8axxMJ419N2osBY?p=preview
It is as simple as:
$modal.open({
templateUrl: 'someTemplateOfTheModal',
controller: SomeControllerOfTheModal,
})
You can refer to this for options.
Otherwise, if we are just talking about how to integrate existing jquery stuff in angular, I would still suggest rebuilding it from scratch in the angular way. Basically replace all jquery trigger/event functionality by pure angular.
For example, a modal can be on or off, might have an overlay or not. The modal itself would probably be used to execute a callback event on yes and not on cancel. You might want to also style it using custom classes so you should take that into consideration. Here are the directives you might wanna take a look if you are rebuilding it from scratch:
ng-if/ng-show (would probably be used to show/hide your modal and/or
overlay)
ng-class (would be used to inject any custom classes you might want
to put on your modal)
ng-include (in case you want your modal to be templatized)
ng-click (to do click events on click of your yes/no/cancel buttons
and/or clicking away from the modal or on the overlay)
You can see that it can get a bit cluttered, so the best thing would be to use angular's $modal service because it has all those features builtin. I think it has everything that you might possibly want from a modal, and you should just style it. But of course, for learning purposes, you might want to reinvent the wheel.
Related
How do I create a popup Angular 1.6 component that accepts several parameters and will be used in several pages. One of the parameters will be dynamic -- set in the ng-click that opens the popup.
The popup scope should be a child scope of the calling page (not isolate), and it should have outputs back to the calling page.
Anyone know of a good pattern for that?
It mainly depends on what front-end framework are you using: if you go for Bootstrap than search for Bootstrap's Modal; if you are using Angular Material than it's called Dialog.
And in terms of how to set up the logic for it, well, there are quite a variety of options here as well. The simplest one I can think of would be to:
bind any variables from the popup using ng-model AND
pass it to a service and have custom logic OR in $rootScope OR in Location
This would be just a simple exammple.
Again, I think it mainly depends on what you actually want to achieve, which is not quite clear. I hope this helps.
For example we have a web app and sometimes we need to hide or show some custom directives or html parts using ng-if/ng-show/ng-hide. What we do, we click on a link "Example Show Link" and our elements appear or disappear.
So, here is the Problem:
When you go to another page/state/controller of course your directive/html part is still visible.
Is there any cool solution to hide this parts?
Except using rootScope or pushing true/false flag in every controller, 'couse there could be a lot of directives and a lot of controller
You can use routes for this, and ui-router is what I think the best one that handles this. When you use routes, only the current states' templates are shown, when you navigate out of the state, its template (together with all the directives in it) are destroyed. It automatically do it for you.
What's the best way to have my views appear in a popup modal?
I have the main dashboard of my app, and then whenever the user wants to add or edit an item on the dashboard I want this to be done via a form in a popup modal.
I know I can use jquery to handle the showing and hiding of the popup. But is there an angular way to do this, or is jquery acceptable in this scenario?
Check this out and go down to the modal section. This looks nice and clean. There is an example of the html and javascript there for you. Your view is a template and can be a html file or inline html inside the javascript.
http://angular-ui.github.io/bootstrap/
Much like everything in Angular, there are a number of ways you could do this. Perhaps the most simple way would be to have the HTML of the modal be hidden by either ng-show or ng-hidein conjunction with ng-mouseover.
I'm actually doing this right now and decided to use jquery ui for the modal. Dragging and resizing is hard to do and my modal requires that. I wrap the modal call in a directive so modal pops up onclick. The mistake I made was using jquery append to add new html. Don't do this. Use template or templateUrl and then put that in your modal. This will ensure all scope vars in your modal will communicate with your controllers.
I am using angular-ui in my project and I wanted to implement a modal window. Most of the components of the library (http://angular-ui.github.io/bootstrap/) are implemented as directives (as expected). However, modal is not - it is implemented as a service. This leads to a strong dependency on the view in the controller (i.e. the controller needs to know that the view uses a modal window, what should not be the case).
My question is: why is modal implemented as a service, not directive? Does it give any benefits?
The $modal directive is quite flexible, and by its API, it supports:
Being triggered on any event you want, since the controller controls when it opens.
Passing data from the controller to the controller in the dialog, using the resolve option
Using any controller or template in the dialog.
Passing data back from the dialog on close to the triggering controller, by its result promise.
While not impossible for this to all be in a directive, I think it could only realistically be achieved by using a lot of options, or a complicated object, which would have to be constructed in the controller anyway.
Another reason for this not being a directive, is that directives are usually for things in a particular place in a page. The modal by its very design is not attached to any element in the page.
I would suggest trying to design an API for a directive that gives the same functionality as $modal, and I suspect it'll reveal that using a service is, on the whole, clearer, and probably more flexible.
My full code is at:
http://plnkr.co/edit/6EQFXL?p=preview
The "delete row" and "delete column" buttons are dynamically created. Right now when I click on them nothing happens. How can I get them to run the corresponding handlers? Is there a better way to do what I am trying to do (make a resizable and editable grid)?
Main Issue
The problem is that your creating the html for the button without compiling it through angularjs. You could just send this through the $compile service to get it to work but that's not the angular way. The better option would be to create a directive for tbody and put code there either as a template or in the compile phase of the directive. There's a great video by Misko Henvrey (lead engineer from angular) about creating directives at http://www.youtube.com/watch?v=WqmeI5fZcho. Also you might want to check out the ng-grid created by the angular-ui team at https://github.com/angular-ui/ng-grid to get an idea of how to put together a semantic grid component.
Side Issue
When trying to think in angular you really need to start thinking of the functionality you need and architecting a solution for the functionality (e.g. the directive (s)). What you've done in this question instead is thinking the traditional javascript way (nothing wrong with that in general), which is to say ok I'm limited by what html gives me and I need to tie my javascript in to the stuff I'm given through hooks on classes and ID's. I highly recommend taking a look at "Thinking in AngularJS" if I have a jQuery background? to get a more complete view of angular vs jquery/traditional javascript.