Is the Utilization of Inline JavaScript in HTML Attributes by Angular considered a "good practice"?

While going through the Angular tutorials, I found a lot to like. However, I couldn't help but wonder if "ng-click" is not essentially just an inline onClick function. My understanding was that the JavaScript community frowned upon using inline JavaScript event handlers in HTML as it was considered a "bad practice."

<img ng-src="{{img}}" ng-click="setImage(img)">

I am curious to know why this approach is now acceptable when working with Angular.

Source: http://docs.angularjs.org/tutorial/step_10

Answer №1

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.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What could be causing my Vue application to not launch after executing `npm run serve`?

These past 24 hours have been a struggle for me. I recently embarked on the journey of learning Javascript, and my choice of JS framework was Vue JS. However, when I run npm run serve, my Vue JS app bombards me with numerous errors that seem to make no se ...

Exploring Facebook Graph API response with Angular 2 Mapping

I am using HTTP calls to access the Graph API in order to retrieve posts from a Facebook page. Here is the code snippet that fetches an array of posts: let url = 'https://graph.facebook.com/15087023444/posts?fields=likes.limit(0).summary(true),comme ...

Trying to incorporate a PHP echo statement into the innerHTML of a button is ineffective

I have a piece of jQuery code that is not functioning as expected: $("#erase").click(function(){ $("#erase").attr("disabled", "disabled"); // Prevent double-clicking $(this).html("Erasing..."); $.post("erase.php", {target: $("#targ ...

Error: StalePageException occurred in the wicket framework

I am currently using Wicket version 6.20. Within a Wicket page, I have implemented an AbstractDefaultAjaxBehavior to capture mouse clicks and their x,y coordinates: class CallFromJavaScript extends AbstractDefaultAjaxBehavior { private static final l ...

What is the best way to sort through this complex array of nested objects in Typescript/Angular?

tableData consists of an array containing PDO objects. Each PDO object may have zero or more advocacy (pdo_advocacies), and each advocacy can contain zero or more programs (pdo_programs). For example: // Array of PDO object [ { id: 1, ...

Webpack does not support d3-tip in its current configuration

I'm having some trouble getting d3-tip to work with webpack while using TypeScript. Whenever I try to trigger mouseover events, I get an error saying "Uncaught TypeError: Cannot read property 'target' of null". This issue arises because th ...

Adjusting SVG size based on the position of the cursor for transforming origin

My goal is to scale an SVG circle using the trackpad (by moving two fingers up and down), with the origin of the transform being the cursor position. Initially, the scaling works as intended, but on subsequent attempts, the circle changes position, which s ...

Is it possible to use a Backbone Model for an unconventional HTTP POST request that isn't

After going through the documentation at and , I tried to make an HTTP POST request to fetch some JSON data for my model. However, due to the services not being RESTful, I ended up using a POST request instead of a GET request. The code snippet I have co ...

What will occur if I invoke response.end in Node.js while asynchronous I/O operations and callbacks are still executing?

When working with Node.js, what happens if you call "response.end()" while I/O calls and/or callbacks are still being executed? Take a look at the code snippet below: var app = http.createServer(function(request, response) { response.writeHead(200, { ...

Align content distributed evenly will not display a division

I am currently using React to code and learning by doing so. I have two different images displayed, each followed by a div element with a height of 20px and a brown background color. I have set the height to "100%" and justifyContent to "space-between", bu ...

Controlling multiple bx-sliders with a single pager using only JavaScript

Is there a way to control 3 sliders using the same pager? I attempted to use the following code but it did not work: <script language="javascript"> $('.mobile_left_mble,.mobile_right_mble,.text_btn').bxSlider({ //pagerCustom: '#bx- ...

Develop a personalized API using Strapi that involves integrating data from two distinct tables

I am relatively new to Strapi, so please forgive my lack of experience. My goal is to set up a custom route for retrieving complex data using two related tables. I have relationships with the "items" and "comments" tables. My approach involves selecting ...

Is there a way to append the current path to a link that leads to another URL?

I am currently in the process of separating a website, with the English version being on the subdomain en. and the French version residing on the www. Before making this change, I have a drop-down menu that allows users to select their preferred language ...

Ways to retrieve the specified data in Javascript in string format

I'm facing an issue where the data I passed from a JavaScript array to a Java servlet and back to JavaScript is showing as "undefined." Check out my JavaScript code below: var buildingNumbers = []; // Let's assume the values of buildingNumbers ...

Strategies for filtering fields in LoopBack based on the included model

Here is my query that I am working on: UserModel.find({ filter: { include: [ "communications", "roles" ], where : { "object_type" : 1 } } }, function(data){ $root ...

Tips for calculating the difference between timestamps and incorporating it into the response using Mongoose

In my attendance model, there is a reference to the class model. The response I receive contains two createdAt dates. const attendanceInfo = await Attendance.find({ student: studentId, }) .populate('class', 'createdAt'); ...

What purpose does the div tagged with the class selection_bubble_root serve in Nextjs react?

Just starting out with Nextjs and setting up a new Next.js React project. I used create-next-app to initialize the code base, but then noticed an odd div tag with the class 'selection_bubble_root' right inside the body. Even though its visibility ...

Occasionally, the function XMLHttpRequest() performs as expected while other times it may

I've encountered an issue with my XMLHttpRequest() function where it randomly works in both Chrome and IE. The function is triggered by On-click, but I'm having trouble catching the error. The only information I could gather is that readystate = ...

Swapping out a subarray within an array containing objects with a fresh array consisting of objects

Here is the structure of my data document: { "_id": "6287a6c5975a25cc25e095b0", "userName": "Robot", "projectName": "TestProject", "projectTypeName": "fixed project", "pro ...

Is there a way to keep track of changes in multiple dropdowns without having to create a separate JavaScript function for each one

I'm looking for a way to dynamically add more dropdowns as my website grows without having to keep adding new functions to the JavaScript code. Is there a solution for this? Currently, I can add additional functions to the JavaScript like this: ...