-1

This has long been a question of mine since I got my hands on AngularJS.

Yes, AngularJS offers a thorough separation between the presentation and the undermine logic. However, I find myself in such a dilemma where sometimes I really can't resist the temptation to manipulate some DOM elements directly from my service, which is obviously not best practice because AngularJS recommends doing it in directives, which I find quite exhausting, especially in situations where I would like to create apps with an immersive experience.

Recently I'm engaged in a native app project using node-webkit. We want to build a multi-document app with HTML5 and Node.js, taking advantage of AngularJS. But I cannot figure out a way of achieving this. As far as I'm concerned, even nested views are neither easy to create nor recommended with AngularJS, let alone multi-windows.

In the meanwhile, I find Backbone quite satisfying in this respective. However, I still prefer AngularJS for other reasons.

So what do you think? Is there any solution to this problem? Is there any open-source project out there? Code examples are also greatly appreciated. Thx in advance.

Isilmë O.
  • 1,668
  • 3
  • 23
  • 35
  • 1
    Can you ellaborate more when you say it's exhausting to manipulate the DOM through directives (I personally find much easier and «safe»)? Can you show us a concrete example so we, perhaps, understand why you find it daunting? – António Sérgio Simões May 26 '14 at 15:51
  • @AntónioSérgioSimões Say, in order to make a Dialog with AngularJS, I need to create a directive. First, if the dialog contains dynamic DOM changing accordingly to user's realtime input, I find directive not of much use (I'm conservative so I would still choose to wrap it with directive though, but isn't it a drag?); rather, I find using jQuery directively much more flexible and concise. Second, to conform with the semantic rule, it's not good practice to put a dialog in the HTML document instead of appending it dynamically. According to your opinion, where should I get this around?Thx – Isilmë O. May 26 '14 at 16:08
  • You can still use plain jQuery inside a directive with the added bonus of referencing directly to the element you want to attach the new HTML to instead of doing a DOM query. – António Sérgio Simões May 26 '14 at 16:34
  • To be added, sometimes I find it's inevitable to do some "dirty" DOM things which fall out of the best practice eg. window.onscroll = function(){}. Where do you think I should put it? Should I create a directive for that and attach it to the root element or should I just create a separate "dirty.js" for that sorts of things? For the latter, it would be problematic to access to the $scope; For the former, however, the directive seems a little unnecessary. – Isilmë O. May 26 '14 at 16:36
  • check my answer below...easier to read the code – António Sérgio Simões May 26 '14 at 16:56
  • I think I've got the sense now. Thanks, Antonio. :) – Isilmë O. May 26 '14 at 16:58
  • 1
    Quote: "even nested views are neither easy to create nor recommended with AngularJS" Have you checked out Angular UI-Router? https://github.com/angular-ui/ui-router I would recommend checking out the videos on the bottom of the page, they very well show how one can create nested views with multiple partials independently from each other. Hope this helps – flaky May 29 '14 at 16:20
  • @flakyfilibuster I did a brief research into it and found it very inspiring and flexible. Thanks! – Isilmë O. May 30 '14 at 02:16

3 Answers3

1

A simple directive to handle onscroll could be something like this:

    app.directive('myScrollWindow',function($window){

    return function(scope,element,attrs) {

       angular.element($window).bind('scroll',function(){

       // do your stuff here
       // for example:
       if(this.pageYOffset >= 50) {
         // do something
       }


       });
       scope.$apply();
     }
   });

scope.$apply() is key here for this to work.

Point being is that you can do pretty much anything inside a directive.

UPDATE

You can add a button and show the modal like this: (I'm assuming you're using Twitter Bootstrap for the modal)

   app.directive('blah',function(){

    function link(scope,elem,attrs){
        var modal = elem.find('.modal');

        scope.openDialog = function(){
            modal.show();                
        }
    }

return {
  restrict:'E,A',
  link: link,
  template:"<button type=\"button\" ng-click=\"openDialog()\">Click me</button><div class=\"modal hide fade\">...</div>"
}
});

element.find() will only look inside the template of the directive. It wont do a full DOM search for the modal css class. This is the beauty of directives

  • If I want to open a dialog when the user clicks a button, should I code another directive serving as an attribute and attach it to the button? Or if it's acceptable to set the "onclick" property to an OpenDialog() function inside the scope? – Isilmë O. May 26 '14 at 17:01
  • OK. Thanks for the effort. I'm setting yours as the accepted. :) – Isilmë O. May 26 '14 at 17:12
  • Thank you. Albeit there are very good answers below :) Thing is, directives can be very very efficient performance wise, like I have stated above, you can do very efficient DOM queries that will only look inside the «scope» of the directive...and once you start using them often, it will become second nature – António Sérgio Simões May 26 '14 at 17:15
  • quick addition here: For anyone seeing above example and speeding off to try it out, notice, that per default Angular only ships with a subset of jQuery where #find() is limited to tagnames. https://docs.angularjs.org/api/ng/function/angular.element – flaky May 29 '14 at 16:12
  • That's right. I should have pointed that out. If you want to make use of the full fledged version of jQuery instead of jQLite that ships with Angular, you need to reference the jQuery core _BEFORE_ the angular core. – António Sérgio Simões May 30 '14 at 10:24
0

you should definitely take a close look at ionic. they're still in beta but made huge improvements in everything from UI to performance.

ionic library is pretty straight forward, angular is great in terms of f/e logic and cordova proved itself so far to be production grade material in terms of API. having (almost) single code base for a cross platform solution, outweighs any other considerations when it comes to have a prototype asap out of the door.

ionic framework docs

cordova API

dannyde
  • 122
  • 4
  • Thank you for the answer. Ionic is a framework of hybrid cross-platform development for mobile devices, while what I mean by "app" here is a generalized concept including webapps and native app run on platforms other than mobile OSs. – Isilmë O. May 26 '14 at 16:15
0

If you are not adverse to introducing another framework, I would recommend Twitter Bootstrap 3 and UI Bootstrap. UI Bootstrap is a set of Directives written by the Angular team. I found it to be pretty comprehensive in performing all of the UI manipulation we needed. Of course, if you need more functionality, you could always extend the directives.

There is even a Directive for the Modal Dialog that works a treat. Give it a look.

  • Good hint :) Still, do you think it is viable to create interactive animation without breaking up with AngularJS? Angular-UI uses CSS3 transition to handle the animation, which is elegant but not that flexible. – Isilmë O. May 26 '14 at 16:49
  • Check out Angular Animations at http://www.nganimate.org/ . It uses CSS3 Animations. I found that there is a very strong community built up around Angular and therefore have been able to find a good solution for whatever I needed to build. However, you mentioned Backbone in your question and because that allows you to get much closer to the metal, it allows you much more flexibility. Realize that you will be writing much more boilerplate code that Angular gives you OOTB. – Matthew at Critical Cognition May 26 '14 at 16:58