Hacker News new | past | comments | ask | show | jobs | submit login

We used to write things like

    <a href=”#” onclick=”doSomething()”>
Then we realized it was bad to couple presentation and behavior, so we made our Javascript unobtrusive, keeping our templates clean. But now we’re back at it again, writing

    <a href=”” ng-click=”doSomething()”>. 
Have we learned nothing?


This seems like a good point that I can't refute - anyone?

Honestly, there's not a huge amount of difference between

  <a href="#" id="show-help-link">Show Help</a>
  <script src="text/javascript">
    $("#show-help-link").click(function() { showHelp(); } );

  <a href="#" ng-click="showHelp()">Show Help</a>
I mean, HTML has behavior in it. A link in itself is "behavior": when you click this tag, go to the page defined in the src attribute. So, as the author says, it's not really a bad thing that templates have behavior in them. In Ember.js, for example, you have an {{action}} handler that is essentially the same as ng-click - "run a function on the controller when this is clicked."

I think it's because needs evolved. When we went away from tables to use stylesheets, the goal was to keep the same html but alter the presentation with css and js (for the animations). But now, it's not just about presentation anymore. Real applications are built and maybe it doesn't make sense to keep the html and throwing away css/javascript on a full-rewrite. Basically, the html we code right now is way more tied to the javascript that it once was. So, having them in two separate files doesn't make that much sense.

Oh, and, you can use $('#show-help-link').click(showHelp); instead of click(function() { showHelp(); }); ! : )

You don't need the src="text/javascript". Only <script> ... </script> is required.

Heh, I meant to specify "type" and not "src", but you're right regardless.

This is a choice you can make in angular - you can do it the other way if you want. It's totally up to you.

We're building webapps - there's going to be behaviour attached to dom nodes. You could use a class instead but in my experience you end up in a worse place. When people do it as classes (or data attributes / whatever else) someone is going to come along and wire styles to those. You'll just end up with a much more twisted coupling of behaviour and presentation. I've unpicked this mess more times than I care to think about right now.

Also, it's really different in Angular - the behaviour is not as coupled. Each element has its own scope - the old "bad" way was wiring up html elements to GLOBAL scope. That's obviously not great.

Edit: so I don't sound so snarky.

The first one requires a global method. The angular one is a method that is tightly scoped and easy to test.

This too

There is an immense amount of guilt and shame concerning the subject of markup and JavaScript living together. It may help if you rationalize it this way.

The second one not HTML at all, rather it is written in an XML-like configuration language which declaratively specifies the structure of the view, in which the attributes use Angular's JavaScript-like expression DSL to declaratively specify how its elements are bound to the behaviors available on whatever controller has been injected into this template. This allows you (or a non-coding designer) to completely change up the connections, appearance or structure of the view while touching no JavaScript whatsoever.

So in this case the markup and the behavior can be intimate, without actually coupling; thus there is no need for anxiety.

Connecting presentation and behavior has to be done somewhere, otherwise your presentation do nothing and your behavior can't display. You shouldn't confuse "couple" with "connect".

Having a "onClickButtonA()" function call bound to a button whose id is "A", and then have the logic associated to the click on that button somewhere in the controller is a completely different thing than having "checkAccountBalanceAndSubmit()" directly in the HTML.

Angular remove 80% of explicit HTML/javascript conversation that were only there to dumbly synchronize input views and model. The rest is just really unavoidable.

The alternative is a slew of loosely-coupled and opaque attributes (IDs and classes), especially where you're not sure if a particular class or ID is used for presentation (CSS) or functionality (JS). How do you handle refactoring when you use some classes for JS and some for CSS?

With custom attributes there is no confusion, and although it goes completely against the separation of concerns and now your mark-up isn't completely declarative -- it's a necessary drawback.

What about some kind of Hungarian notation for classes?

pBlue bWidget?

I've never done this, just wondering.

if you have functionality class/ID, do you really have separate concerns or do you just have moderate/loosely coupled concerns?

Well the most disturbing thing about this syntax is for sure the use of parentheses. Drop them and you will get old good ng-click="doSomething" which doesn't differ at all from class="ng-doSomething" or data-ng-click="doSomething".

But parentheses try to lookalike the onevent attributes, which a) everybody doesn't like and b) immediately invoke javascript code

In AngularJS point b) can't be the truth - there is for sure some layer of expression evaluation, and that is what disturbing - as an experienced javascript developer you know that this layer exists, but you can't easily see what happens inside that layer - AngularJS hides that from you.

In most cases in traditional JS development - nothing really happens in this layer, it's just a dumb method invocation in the context of the view and has dom event as a single argument - this is clearly visible in libs such as Backbone.

But in Angular this layer of expression parsing and evaluation does exist - and you don't know what kind of magic happens there and how thick, maintainable and overridable this layer is. This possibility of dirty magic - that really disturbs me in all the simple tutorials of AngularJS, so I don't have courage yet to give it a try in a serious project.

My best attempt:

HTML already has a bunch of behaviors embedded in it. Links, styles, dropdown menus, input fields, radio boxes, etc. The angular devs are simply embracing the declarative nature of HTML and extending its available behaviors. In that respect, angular is actually treating HTML more like it was intended to be treated.

And I agree with the OP's lamentations about the javascript being completely divorced from the HTML. You end up with code that is so decoupled it's a major undertaking for someone new to your project to figure out what's going on. In an angular.js app, all they need do is look at the HTML and they can get a good idea what's supposed to be happening and where.

edit: And the truth is, jQuery apps aren't polluting the HTML any more than Angular apps, they're just doing it in the form of additional CSS classes and IDs and "data" attributes. In that respect, you could say that jQuery pollutes the css declarations.

data attributes are baked in to the html5 standard

This is my #1 complaint about angular - I keep hearing good things about it and going to try it, then I see markup like this and can't get myself to

Strongly suggest looking beyond this if your concern about Angular is that it is returning us to an old approach. Angular, on the contrary, in my experience, is a broadly conceived vision of how to rethink and move browser development significantly forward. I have been waiting for something like this. The key part of that ng-click is that it's an Angular 'directive'. I recommend adding AngularJs to your app to do a simple experiment of writing a few directives of your own; see if that doesn't light a bulb.

What solution are you comparing it to?

    <a id="clickable-link">
And the putting something like the following into a js file:

I find the declarative markup of a well-written angular app to be quite clean and easy to read, much more so than the alternatives.

The article did go on to say that there's no perfect place to put it but it still has to live somewhere. To expand on that, an event listener, by definition, is going to contain some DOM and some business logic. So no matter where you put your listener half of it will be out of place and reliant on some other code (attribute/function names) that may change in the future. Placing listeners in the DOM is the lesser of two evils simply because it is easier to write backwards compatible business logic/javascript than HTML.

The difference is onclick="doSomething()" runs doSomething() in the global scope. Not good!

ng-click="doSomething()" runs doSomething() in the scope of the controller that contains the element. Good!

Separating content from presentation matters.

For documents.

Applications are not documents.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact