Ultimately, the key point is that your view code needs to be connected to your application logic in some way. AngularJS best practices recommend creating your own models - objects that represent your business domain - and attaching them to the scope. Consider this example:
<img ng-src="{{img}}" ng-click="myProfile.setMainImage(img)">
myApp.controller("ProfileController", function($scope, myProfile) {
$scope.myProfile = myProfile;
});
In this scenario, the view instructs that when the image is clicked, it should call setMainImage() on myProfile. The actual business logic resides within myProfile
, enabling it to be tested and managed separately. The view simply serves as a bridge.
In a more conventional jQuery setup, you would need to write something like the following:
$("#someId img").on('click', function() {
var img = $(this).attr('src');
myProfile.setMainImage(img); // How does myProfile get accessed here?
// How does it update the view?
});
The JavaScript community generally agrees that managing large applications using this approach is not practical, mainly due to the disconnection between views and model objects (as evident from the comments in the code sample), which is why frameworks like Angular exist.
While the traditional jQuery code may not be ideal, there are still uncertainties about the ngClick
approach. Let's compare it with another popular MV* architecture framework, Backbone. A user raised concerns about AngularJS in relation to Backbone in a RailsCasts episode:
Is AngularJS really a good idea? The use of ng-show
, ng-repeat
, ng-class
reminds me of old frameworks like Java's JSF. It also enforces obtrusive JS with ng-submit
and ng-click
.
The concern is that your view could become cluttered and overly reliant on these directives. Other frameworks like Backbone prioritize separation of concerns between presentation and behavior, resulting in a structured client-side application (MVVM).
A similar response was provided...
In a Backbone environment, event handlers are set up on elements within a view object to interact with model functions. Callbacks are also established on model events to trigger updates in the view. In contrast, Angular treats the DOM itself as the view by setting up event handlers through directives like ng-click
, ng-submit
that delegate to model objects or respond to model changes affecting the view.
The main difference lies in how declarative Angular views describe what the view represents compared to imperative approaches like Backbone, where the focus is on defining what actions the view performs. Although Angular sets up callbacks automatically, it ultimately simplifies the process without introducing additional dependencies.
So, using
<a ng-click="model.set({selected: true})">
doesn't impose more dependencies than...
events: {
'click a': 'select'
},
select: function() {
this.model.set({selected: true});
}
...but it significantly reduces the amount of code required. ;)
(Note: Ideally, the Angular version should utilize
<a ng-click="select()">
, where the
select
method on the scope mirrors the functionality of the view's
select
method in the Backbone example.)
If the presence of event hooks in your markup is a genuine concern, Angular's declarative nature offers a more streamlined approach where markup defines the view's characteristics and facilitates two-way binding between events and views. This results in less boilerplate code for event handling and improves overall view comprehension.