5 ms·
Some AngularJS pitfalls
- marknutter 13y agoFor Minification, Brian Ford's ngmin grunt task works perfectly. The OP says they haven't tried it which to me suggests that they may not be using grunt at all, which is a mistake. Grunt takes care of a lot of workflow and deployment details, including minification, and should be part of every javascript developers toolset regardless of whether or not they use Angular.js. For the "Directives are never 'done'" issue you should be able to attach any jQuery plugins to the DOM in question inside the directive compile function.
- SanderMak 13y agoCorrect, the particular system I encountered this minification issue has an Ant-based build (which calls r.js for concatenation and minification). I'll have to check on your compile suggestion. I tried lots of things, including using the postLink etc. Do you have an example?
- marknutter 13y agoHere's an example using the jQuery UI draggable plugin: http://jsfiddle.net/marknutter/hSbjX/4/ http://jsfiddle.net/marknutter/hSbjX/4/
- SanderMak 13y agoThanks! I also just found out about angular-ui-utils, where they have a generic pass-thru directive for initializing jQuery plugins. Interestingly, they opted to use $timeout inside the compile function: https://github.com/angular-ui/ui-utils/blob/master/modules/jq/jq.js https://github.com/angular-ui/ui-utils/blob/master/modules/j... Wonder why that is, are there cases that would otherwise break?
- marknutter 13y agoI'm not sure, that's a good question.
- KaoruAoiShiho 13y agoYou don't need grunt, you can use ngmin with any type of build process.
- marknutter 13y agoRight, I should have mentioned that. There are also alternatives to Grunt, but regardless, some sort of task running tool is a must in my book.
- TeamMCS 13y agoMy biggest issue with AngularJS is the inflexibility of it to play nice with existing '1.0' sites. Almost all the sites I'll develop take advantage of progressively enhanced components or at minimum, widgets that are bootstrapped server side. Angular wants you to load everything via AJAX - that can get heavy very quickly. This is also evident within the codebase. You find yourself dancing around DRY violations as you pass models to your markup rendered server side and also serve the same/similar content to Angular via JSON. Now this aside, Angular wouldn't require much work to let it play an enhancement or migration role. You can already see Google have implement their own 'private' method on the homepage of Angular. Another problem that grates me about Angular is dynamic routing and loading additional Javascript on the fly. I was recently building a portlet based site. The intention was to make each module entirely configurable by other developers - that meant passing control to their controllers and allow them to enhance routing. As it stands you have to do it declaratively or using some nasty hacks.
- avolcano 13y ago> Almost all the sites I'll develop take advantage of progressively enhanced components or at minimum, widgets that are bootstrapped server side. Angular wants you to load everything via AJAX - that can get heavy very quickly. I'm surprised that I haven't seen a library for any JavaScript framework that elegantly handles loading JSON returned within a server-side template. It seems like the best of both worlds - use your server-side template, but then also get the data as JSON so that you don't have to do a second request to populate your Angular $scope with data. The easy way to implement this would be a library that automatically added <script> tags containing the JSON that you could then reference from your Angular template. It could even wrap the JSON in an Angular module of some sort to keep your global namespace from being polluted.
- SanderMak 13y agoAgreed. I tried to explore this issue a while back: http://branchandbound.net/blog/web/2012/11/unify-server-side-client-side-rendering-embedding-json/ http://branchandbound.net/blog/web/2012/11/unify-server-side... Turns out that using script-tags is somewhat problematic, but as a comment points out, data-attributes could work.
- avolcano 13y ago> Another option is to completely hide elements, or even your whole application, until Angular is ready. Angular provides ng-cloak to this end. My issue with this is that it doesn't solve the problem of binding to asynchronously-loaded resources. You have to manually implement your own ng-cloak logic, or use ng-bind, to not have {{mustaches}} waiting for data to be loaded. Compare to Ember, where {{mustache'd}} data-bound bits aren't rendered until their bound variable is defined. (the, other fix, of course, is to do something like `<span ng-hide="foo != undefined">{{foo}}</span>`, but that doesn't scale particularly well)
- oinksoft 13y agoYou are somewhat misinformed: If you are using more than one template, this is a non-issue. Only the HTML from the initial page load will ever display template bindings, that being the purpose of ng-cloak, ngBind, etc. $templateCache can be pre-loaded with something like the ng-templates Grunt task, so excessive HTTP requests are not an issue either.
- marquis 13y agoAnother good reason to use ng-bind is that you have your UI ready to localization and could save a lot of work later on. We use a combination of ng-bind and ng-cloak, where the first page view is fairly light so the loading time is insignificant. It's also an easy matter to write your own Loading directive which could pop up a loading notification modal for example, though I personally tend to hate those - I'd rather have a light page view that shows me something to start looking at and have the main data lazy-load in the background.
- Oculus 13y agoSometimes the drawbacks of a framework are more important than the features. Most competing frameworks (i.e. AngularJS, Ember.js, Knockout) keep on par with one another when it comes to features. Their real differences comes out in the drawbacks of how those features were implemented and whether you're willing to deal with those certain drawbacks.
- greaterweb 13y agoNice writeup, here is my input on the points OP makes. The flickering UI A quick fix would be to extract the problematic markup, place in a separate template file and leverage ngInclude[1]. If you find yourself having many instances where this is a problem, chances are you aren't doing a good enough job of breaking up your application into controllers, page components, directives, etc. jQuery and Angular In my opinion the example is little weak in terms of demonstrating a pitfall of AngularJS. Based on AngularJS best practices you'll find yourself only doing any sort of DOM manipulation in the context of a directive (much like your example). Bringing jQuery into your Angular app for the sake of using .hide here probably won't make much sense. Chances are pretty good you'll leveraging directives such as ngShow[2], ngHide[3], ngIf[4] (version 1.1.5). No need to bring jQuery in for that. If there is indeed a valid reason to bring jQuery into the project, I'd say the responsibility lies more so on the developer ensuring the dependency is met. Minification With the addition of ngmin[5], this isn't necessarily a pitfall just something to consider in your workflow. There is a ngmin grunt task[6] that works as advertised! I've been using it for quite some time now and never an issue. My thought overall though is if you've conceded minification is a step in your project workflow, you'll be using tooling to make that easier. Bring ngmin into the mix and all is well. Directives are never 'done' I would suggest looking into using $watch[7] within the scope of that directive or making use of compile post linking over the linking used in the example. Check out the compile section [8] of the directive guide for more information there. [1] http://docs.angularjs.org/api/ng.directive:ngInclude http://docs.angularjs.org/api/ng.directive:ngInclude [2] http://docs.angularjs.org/api/ng.directive:ngShow http://docs.angularjs.org/api/ng.directive:ngShow [3] http://docs.angularjs.org/api/ng.directive:ngHide http://docs.angularjs.org/api/ng.directive:ngHide [4] http://code.angularjs.org/1.1.5/docs/api/ng.directive:ngIf http://code.angularjs.org/1.1.5/docs/api/ng.directive:ngIf [5] https://github.com/btford/ngmin https://github.com/btford/ngmin [6] https://github.com/btford/grunt-ngmin https://github.com/btford/grunt-ngmin [7] http://docs.angularjs.org/api/ng.$rootScope.Scope#$watch http://docs.angularjs.org/api/ng.$rootScope.Scope#$watch [8] http://docs.angularjs.org/guide/directive http://docs.angularjs.org/guide/directive
- sequoia 13y agoNice writeup! I'm using angular now on a work project for the first time. My observation here is the same as what I've had for many "look how easy it is!" frameworks: A lot of frameworks sport "look how easy it is!" syntax, but using the easy/short syntax actually isn't adequate in some (sometimes most) circumstances, and often it isn't even "recommended." So you start using the longer, more explicit syntax, and all those short/sweet syntax features are out the window. For example, the easy-to-read {{obj.prop}} data-binding syntax is basically dis-recommended here with three workarounds given (use ng-cloak, declare databindings on element attributes, externalize & `include` the offending markup). Once you have 3 different workarounds for what's basically the most fundamental framework feature, I can't help but wonder "why offer this short/sweet/brittle syntax in the first place? Most 'power users' can't really use it." The dep injection one in particular- basically any shop worth its salt is going to use a minifier on big JS applications- none of them (us) can use the short dep injection syntax. Why even teach it/include it at all? I guess it gets people up & running faster, but eventually you have to deal with these pitfalls.
- oinksoft 13y agoWhy even teach it/include it at all? I fear that other developers will read a comment like this three months down the road and take it hook, line, and sinker. It is in line with the narrative that AngularJS and similar tools hide their complexity/inflexibility, and that the up-front examples are marketing fluff. I know I am guilty of this when I look to comments like this one for the "on the ground" perspective. Real-world AngularJS applications use multiple templates and {{ o.p }}. {{ o.p }} is the recommended way to render scope 99% of the time. ngmin[1] solves the DI minification/annotation problem transparently and is trivial to integrate into any existing build process. [1] https://github.com/btford/ngmin https://github.com/btford/ngmin
- sequoia 13y agotake it hook, line, and sinker. :( I'm not a framework developer at all, just a user; this is just my observation. Maybe it's incorrect or poorly informed, just how it appears to one person. Anyway I'm not trying to sell anyone anything, neither am I a fisher of men, so feel free to spit out my tackle. :)
- KeyBoardG 13y agoThank you so much for writing this. My company is planning a move from Fat-client + in house server model to web based likely a SPA solution. I've spent the entire weekend pouring over JS frameworks and have had a rough time trying to compare Angular vs Ember vs Knockout. From a newby, they all seem to be very similar without having written large systems with each to compare.
- beefsack 13y agoSome suggestions from someone using AngularJS in a significant sized commercial project, which manages pages with complex DOM structures with tens of thousands of nodes on some pages: * Don't modify the DOM with anything other than Angular, not with jQuery, not with anything. You will create a maintenance hell for yourself if you try to do things Angular isn't good at, but if you work well within it's strong areas you will achieve bliss. * Make everything a directive if possible, Angular performs much better when you are dealing with much smaller scopes contained in directives. * Angular watchers (including ng-repeat) can be very slow when handling large complex data sets. Create a $watch on the set length, and use that to create a flat index and ng-repeat over the index.