I know it is bad practice to have the DOM manipulation in anywhere other than directive. but I do not understand why is it a bad practice to have the DOM manipulation in the service/factory as we can reuse them.
I have searched online and also found the same question on stackoverflow
stackoverflow question
but still not clear with the answers.
Angular follows declarative principle which means
a style of building the structure and elements of computer
programs—that expresses the logic of a computation without describing
its control flow
At the same time services in angular were introduced to contain business logic. If business flow is complex - imperative approach suites better.
In such a way if you have DOM manipulation in the service you probably violate separation of concerns principle, as you are coupling UI and business layers. And coupling itself eventually ends up in spagetti-code when this "reusable" components (according to new requirements) should look a bit different in the modules where they were integrated
Directives, by definition, are always attached to a DOM node. So when we create a directive, it either expands or replaces the DOM node.
services are engaged with directives so we are able to manipulate view of an app through directives. however, there are cases where you might need to manipulate DOM element(s) via a service, like in a modal window.
I have a rule of thumb for situations like this. can DOM manipulation be done directly with the attached node? and answer to this question tells me if I need to use a directive (yes) or a service (no) but overall it depends on complexity of your project as well.
Related
I’ve been searching for the best way to handle modals in angular and I'm getting the impression that they need to be separated from controllers in order to achieve separation of concerns in MVC.
However when it comes to implementing this using a directive or a library out there I don't see the need for such massive overhead of adding so much code. Effectively it seems as though we are doing exactly the same thing but with more calls and events kicking off as compared to directly showing a bootstrap modal in the controller or service using jQuery as easy as:
$scope.saveChanges = function () {
$('#messageTitle').text('Done');
$('#messageText').text('Changes have been saved.');
$('#message').modal()
}
Porting a directive to handle the dialog is in effect showing the modal with additional steps and setups between dependencies etc. within angular, external libraries and/or custom code (whichever way it is applied). It's really like having a more simplified method call to a utilities method in some utils file that will just show the modal using jQuery. Again, I would be enlightened to know why this is not case which I expect from more experienced angular experts.
Apart from the fact that it is assumed a correct working way to do it, is there a reason why the DOM should not be referenced inside a controller. Could it have an effect on things like i.e. performance, buggy code, testing etc.?
I know that because it makes test cases easier is one of the reasons. Again, a valid reason however testing is not much of an issue having the DOM in business logic as in the code above if tested right. If there are, even more pressing cases for this, what are they? If any what is the best and most efficient way to achieve separation of the DOM from controllers/services if the same applies to services?
Background into current explanations:
What's the correct way to trigger jQuery DOM Manipulation from within a controller?
Separating DOM manipulation from Angular controllers - Best Practice wanted
AngularJS - why manipulating DOM in controller is a bad thing?
Why is it considered a bad idea to manipulate DOM in controllers?
From my understanding, these are the main reasons why a controller should not manipulate the DOM:
Testing. Test cases or test steps can be made well-structured and very easily testable when testing logic in controllers. Here what is tested is truly what a controller should be responsible for (Model manipulation).
Applying well-structured MVC code at the angular code base. Separation of concerns again gives a plus mark for testing but also makes code more manageable and well structured.
I would be happy to hear more detailed alternative answers to completely confirm and explain that any DOM manipulation what so ever is a bad thing within a controller. On the contrary it would be interesting to know whether there are exceptions. For the information of others and my attempt to answer, the reasons above are the most commonly known reasons and thus probably the only reasons to my knowledge, which fair enough are acceptable reasons at this point.
I have a performance issues with Angular (as many others). I wish to change only the view layer to either reactjs or Mithril. I found examples of React js (for example http://www.bimeanalytics.com/engineering-blog/you-put-your-react-into-my-angular/), but not of Mithril.
Can anyone advice to the pros and cons of using Mithril as an angular view vs Reactjs?
Thank you!
I don't think there's an objective answer here, and as a Mithril user I have my biases, but here is what I think.
In terms of philosophy, Mithril and React are quite similar: you write view functions that describe how your app should look at any given time. In terms of rendering performance, I don't think there's a clear winner. There are links / blog posts that say Mithril is faster than React, and vice versa.
So instead what I think you should focus on is:
1) Which API do you prefer? With React you should use JSX lest you have to reverse engineer their documentation. Mithril also just has one lifecycle hook (the view function), whereas React has several (such as shouldComponentUpdate) -- do you need all those hooks?
2) Community support -- React is the clear winner here, and the fact that there are existing examples of integration with Angular is a win.
3) Compatibility - DOM redrawing / diffing in React is done when data changes, just like Angular, but Mithril's redraw is centered around user interaction (such as clicks, route changes, ajax requests). You can manually redraw, but that's less desirable. I don't know how well Mithril will fit into an Angular setup.
Should you decide to use Mithril, I'd encourage you to use the Google group (https://groups.google.com/forum/#!forum/mithriljs) as a resource, or at least report back on your experience.
Mithril and React have many similarities. I've used both of them and here are some pros and cons.
Mithril
Pros: It's loading times are very fast. This is because it's templates are compiled first and then served to the browser. You can write Mithril views in JavaScript. Small size, good documentation and doesn't force you into a predefined structure.
Cons: Small API can make it unsuitable for larger more complex projects.
ReactJS
Pros: React's one-way data binding means that it's easy to see where and how your UI is updated and where you need to make changes. It also provides server-side rendering, virtual dom support, good debugging tools, easy to write tests, easy to reuse components, flux architecture patterns, and extensive SVG supports etc.
Cons: Heavy on memory compared to Mithril, not a complete solution as it mainly focuses on the view, and need to learn a new syntax etc.
In my view, React is overall preferable. But, if your application doesn't need all these extra stuff that React provides, you should go with Mithril.
Its common knowledge that DOM manipulations should not be performed in AngularJS Controller, its very hard however to find why exactly is it a bad thing. All the sources say its difficult to test and because controller should be used for communication between directives, but fail to illustrate with code why this is a bad thing.
From my understanding I would think that controller, unlike directive, is not associated with any specific HTML, hence all the DOM modifications controller would do would very possibly fail. This would sure complicate development and testing.
Controller in directives being executed before link functions of child directives would also fail as the controller might not be aware of what the actual HTML of the child directives is. Link is executed after controller function and might modify HTML structure.
I hope I make sense here and if someone could clarify why manipulating DOM from controller is a bad thing, maybe some code exampleor link that explains it well that would be great.
The reason it is more difficult to prove their point with a code sample is that the reason can't really be represented by a short code snippet (short enough for Stack Overflow). It is really a maintainability precaution. Over the long term, you want to be able to independently alter the logic behind controllers and views independently, because otherwise a coupled controller and view pair tend to stay that way and limit each other in their ability to change their functionality without breaking the other. As soon as you decide to change anything about the view, you have the chance of making your controller code break without even touching it.
Testing becomes easier over time because the more tests you have, the more you wish that things were more modular and dependent on as little variables and parameters as possible.
Again, it is maintenance that drives this suggestion. The problems listed above might not be that bad starting out. But imagine adopting a project that you didn't build from the ground up and know all the intricacies behind the coupling between controller and view that hold this application together. What if your application reaches so many thousands of lines of code that it would be impossible for you to know all these intricacies even if you DID build it from the ground up?
For a more general understanding of why design patterns like the one you have alluded to are necessary, you can refer to this google search that will take you on a journey as long as you are willing to take. And for a general understanding of why design patterns even exist and why many people end up suggesting the same thing over and over again, you can refer to one of the catalysts to the introduction of design patterns, Christopher Alexander. He shows us that patterns are what they are because they work well and people repeat what works well.
If you look at the ever so popular question "Thinking in AngularJS" if I have a jQuery background? you will get some hints.
One of the biggest factor that i think DOM manipulation is neither needs nor done is because Angular uses declarative approach when it comes to DOM linking as against the imperative approach that you would use with direct DOM manipulation. Some of the answers detail this difference between declarative and imperative approach.
With jQuery you tell the DOM what needs to happen, step by step. With
AngularJS you describe what results you want but not how to do it.
More on this here. Also, check out Mark Rajcok's answer.
A more comprehensive treatment of this topic is also available here What is the difference between declarative and imperative programming
With such an approach the controller implementation is simplified, and we start to get real value as code base size grows and complexity increases.
My perspective is bit different and covers more than testing. It is the ability of the designer to have control over the HTML layout that otherwise would be taken over by writing code inside of the Angular Controller. Consider the following snippet (it is just a simple example)
<div ng-repeat="article in articles">
<p class="article-body">{{article.text}}</p>
</div>
This example just iterates over a collection and prints article in a separate paragraph tag. While it is certainly possible to loop over the collection in an Angular Controller and dynamically generate paragraph tags with text inside it. It will take away designer's capability to modify look & feel. Hence, If there is a requirement to show the article title, instead of doing this
<div ng-repeat="article in articles">
<span class="article-title">{{article.title}}</span>
<p class="article-body">{{article.text}}</p>
</div>
the designer will now have to locate Angular Controller code to modify DOM manipulation. Just compare above two approaches and guess which one will provide more flexibility.
I know that this has been asked previously, most notably here.
However, the answers seem to me quite abstract and I find my self quite confused in practice.
The .vs answer seem to be:
Polymer (and more correctly, Shadow DOM) create the ability to not
only compose bits of HTML, but to encapsulate them as well. This is a
fundamentally new capability and one that can be used with any other
templating system or framework to enhance their power.
Which doesn't really tell me all that much, as far as I understand angular directives do pretty much the same thing in practice, although polymer elements might be a bit more efficient performance wise. I'm sure that "encapsulate" has some kind of deeper meaning here in this context that I am not comprehending.
Let's say I'm developing an AngularJS web application. When, how and why would I use polymer elements over angular directives?
Would polymer elements be used instead of angular directives, if so when would one use one over the other? Or would angular directives be implemented in terms of polymer elements?
You're really asking two different things, "What's the differences when implementing/building components vs. using one?"
Consuming components
In the foreseeable future, you use both together. It doesn't matter what technology/library a web component is built with or what vendor makes it. Simply bower install (or similar) and use the components that make sense for your app.
What matters is that everything will be DOM, meaning elements will work seamlessly together. The interop story is great. Here's a POC of an Angular directive data-bound to a Polymer element: http://ebidel.github.io/polymer-experiments/polymer-and-angular/together/
Building components
Building elements is a different story at the moment. Polymer's approach is to center itself around all things web components. Angular was built before the time of web components, so things are a bit different.
Angular directives are a way to build custom tags/components. Polymer and the Custom elements specification is the standards-based way to do that.
How you build a Polymer-element is extremely declarative. Angular directives are mostly defined in JS (with the ability to reference a template file).
Because Polymer elements using Custom elements, inheritance is simple. I'm not sure of the inheritance story in Angular directives/
Polymer elements use Shadow DOM. This gives them encapsulation of DOM and CSS. Styles you define in your element don't bleed out and page styles don't bleed in. I could be wrong, but Angular directives do not have any notion of style encapsulation. It's a hard problem that the Shadow DOM spec gives us for free.
The data binding concepts are similar
would angular directives be implemented in terms of polymer elements
Eventually, Angular will adopt some of the evolving Web Component standards. This will be true for all frameworks. Ember just made their 2014 plans known, which include web components. For example, Angular.dart already uses Shadow DOM for directives.
Polymer elements (custom elements) are interoperable with other custom elements by default. This is because they're just DOM. DOM elements work well together :)
Hope this helps!
I have up to 63 elements that get updated when one changes, do I need a View for each one?
What is the correct way to handle this?
I have a tree structure in my html, where nodes are related to other nodes at different levels.
I wrote js code to handle checking and updating, but that was pre-backbone. I can write the code, I just don't know if I need a different view for each element and what the best practice is.
Each view in Backbone is an abstraction of an visual interface unit, backed by business data(model/collection). Wrapping each responsive element as a view is possible, but rarely the best decision, for that generally means the granularity of abstraction is too fine, which may cause the degradation of efficiency and maintainability.
To effectively benefit from Backbone, designer should think in a big picture first. Many people tend to design/write static HTML code first, then inject dynamic JavaScript later. I don't think that's a good approach. It's better to partition your complex system into several relatively simple and well-defined modules, wrapping visual parts into views and business data parts into models/collections. As for DOM elements, they are just (views') implementation details and will naturally follow the definition of views.
To sum up, rather than decide how to map pre-existing DOM elements with views, decide how to implement pre-designed views with DOM elements.