Why do we call components/controls views?

Continuing the discussion from Understanding how to architect a screen:

[quote=“alexspeller, post:2, topic:4910, full:true”] No, a view is an abstraction around a dom element and should primarily be concerned with handling dom events (and turning them into application-level actions).[/quote]

I am new to Ember (and wonder when I am going to stop saying that) and have struggled through the Ember cliff, with this being one of the difficult issues.

If a view is an abstraction around a DOM element (a control, a link, an image, a horizontal rule, a field element (text box, radio button, etc), etc) why do we call it a view? This really confuses me - it’s not the “view” in MVC? it’s a control/component on the view.

Can somebody explain this? Am I missing a principle or concept?

And I would seriously suggest changing that to make it easier for people to understand.

Yeah, I’m struggling with this too. Apparently Components are subclasses of Views, and are related to Helpers, but none of them work like Templates.

Not sure if I’ll be of much help here, but @end_user is correct in that Ember.Component is a subclass of Ember.View. There seems to be a bit of confusion around templates here though. Views can have a template but templates can’t exist without a view. Ember will automatically instantiate a View and that view will automatically use the template in the location its expecting.

For example, if you’re using Ember-CLI and have a file called index.hbs in the templates directory, but don’t have a file called index.js in the views directory, Ember actually instantiates a view for you and then since a template exists for that view it will be used.

Hope that helps clear things up a little.

Here’s another way of thinking about it:

If you create a new route and use all the default wiring, the template from that will get a free view. This view represents the DOM element that wraps the template. In other words, the outermost element in a template is not actually the wrapper, the view is.

The function of the view is to translate any browser event or DOM-aware function (like a click or a jQuery function) and turn it into some system-level event, often a message to a controller action. The free view you get with a template is good for catching and working with interactions that apply to the whole template, like gaining or losing focus.

A template can ALSO have user-defined views inside it, which are perfect for things like working with clicks and mousewheels on individual parts of a template. These do not need to have separate templates- if you use the block form, you’re basically saying you want to do something with the events that happen inside the view block.

A component is a special case of this where you have a bunch of behavior that’s not specific to your application you want to reuse. You get a view, a controller, a template, and you declare a public API for the application to use. Think things like input fields, date pickers, and file upload boxes. They are reusable across applications and developers, and are meant to be agnostic and shareable.

This isn’t that far off from the classic MVC definition of view. Everything in a view deals with a particular presentation of the state stored in the controller. Separation of concerns means that state can represented as the default handlebars template, XML, a tone poem, a neural interface, or whatever. Ergo, if it’s “HTML aware”, it better be in your view.

1 Like

Sorry my reply has been so slow, I was laid up for a few days due to an old injury.

I want to say “Dude, that was an awesome post!”. I don’t like the word “dude” but sometimes is can be given in a complimentary fashion. Than said, most of that post I would have to break down to understand.

So

<script type="text/x-handlebars">

Is the view? But what you’re suggesting is that an actual Ember View object is being created to back the template? Ok, I can go with that, a view is actually composed of two things, the template via HTML and the View object created in the “code behind”. To me the view is just the template in HTML, this could be better explained.

But what is this:

{{view Ember.Select prompt="Select One" content=controller.selectContentType optionValuePath="content.value" optionLabelPath="content.label" valueBinding="item.selectContentType" }}

Ember (or Handlebars) is calling that a “view”, it’s name is “view”, but that is not an MVC view. To me that is a control/component. But Ember has an object called Component, but for the life of me reading the documentation did not help me.

Now reading the documentation on a View I thought I understood it’s a wrapper around HTML elements/tags to group them and give them non-standard behavior (or to make a component you want to use in multiple places). And those HTML elements will be wrapped with a tag of your choice.

But that is not the “view” in MVC, it’s a component. Unless I completely misunderstood the documentation and you’re telling me that that Ember.View object is wired behind the scenes to each handlebars template.

If that is true the text on the “core concepts” page needs to be totally redone to explain that concept. The word “View” as a topic header does not even appear on that page leading my to believe that MVC in Ember is MTC (model,template,controller).

Am I missing something?

You’re close, but I don’t think you’re all the way there yet.

There’s no “business logic” in a view- traditional MVC or ember. Anything that’s writing to or reading from your API, dealing with application state, talking to other controllers, etc. should be handled in your controller or your route. The primary purpose of a view, as the documentation states, is to turn browser events into “semantic” events. It’s a beautifully terse statement, but it can be a little cryptic if you don’t know what you’re looking for. Let’s talk through some examples:

“Click” is a browser event. So is swiping, inserting or removing a DOM element, expanding or contracting an accordion or whatever. These are things that could happen in any application, whether they’re Ember apps or not, or whether they’re your application or not. They’re just dealing with the magic of HTML and browsers.

A semantic event is something that’s particular your application. Submitting a form, toggling a property, going to a route- these are things that matter to your specific application, and would need to get done whether you were clicking a button, selecting something from a dropdown, howling at the moon, or punching the box in the perfect place.

If the user does a thing and an action happens, “does a thing” means view, “action” means controller. Here’s a magical piece of code that made this sink in for me:

Ember.View.extend({
	click: function(){
		this.get("controller").send("submitAnswer");
	}
});

The view captures the click, and sends a message to the controller to do something. Note that absolutely none of this required templates. Some templates need their own view (partials just use their parent view, and “render” lets you set a specific view, as counterexamples), but a view does not need a template. Two examples:

// Some view named coolTemplate
Ember.View.extend({
	templateName: "superCoolTemplate"
});

{{view coolTemplate}}

This will render a template named superCoolTemplate, and you could also attach all kinds of event handlers to it. For contrast, check out this:

// Some view named upvoteSinger
Ember.view.extend({
    click: function(){
        this.get("controller").send("upvoteSinger");
    }
});
{{#view upvoteSinger}}
    <div>Click me!</div>
{{/view}}

No template, all the HTML was “inlined” to the view because it’s in block form. It still handles all the same events, and has the benefit of being really flexible if what’s inside the block changes from instance to instance:

{{#view upvoteSinger}}
    <div>She's a good singer, right?</div>
{{/view}}

Same click handler, sent to the same controller action, different HTML. The default HTML element wrapping any view is a div, but can be set to whatever, so you should really never do something like this:

{{#view someView}}
    <section class="some-class">
        <p>Saying something important</p>
    </section>
{{/view}}

When you could do this:

// View named "someView"
Ember.view.extend({
    tagName: "section",
    classNames: ["someClass"]
});

{{#view someView}}
    <p>Saying something important</p>
{{/view}}

When I said the templates from your routes get a free view that you can attach events and stuff to, that’s true, but it’s just one of their several uses.

What makes this different than a component is that a view still knows something about your application- like knowing that “click” means “upvote.” A components knows absolutely nothing about your application. It just gives your application an API to get or set its data. Think of a datepicker- you write:

{{datePicker componentDate=myApplicationDate}}

This component might put a control in your template that looks like a textbox, pull up a calendar when you click on it, and store the selection. That selection (“componentDate”) is exposed (and potentially even preset by the controller) by binding its value to the controller’s variable “myApplicationDate.” Whoever wrote that component doesn’t need to know that you’re using to select birthdays or whatever. Do you see how this is a special case for a type of view you might use? Views are reusable across YOUR application, components are reusable across ANYONE’s applications.

Lastly, some general MVC statements:

  • Remember that M, V, and C are all about programming logic. The confusing, dopey way I was taught this concept was “Models are databases, Views are screens, and Controllers are the programs.” This isn’t a healthy way to think about it. Rather, models are what talks to the database, views are what create something like HTML that will be rendered to a screen, and controllers are handling actions and temporary state. An actual HTML template isn’t any of these things, in traditional MVC or in ember. It’s the output of a view.
  • Ember isn’t traditional MVC, but I don’t think it’s because of what you’re describing. In traditional MVC, the user interfaces directly with the controller, while in Ember it happens via the view. I think this makes a million times more sense in a web framework, but I don’t think it’s strictly the same implementation.
  • Templates and routes aren’t a part of the traditional MVC story, but not because are minor or because MVC is broken. It’s because templates (even handlebars templates) aren’t really logic, and URL routing is incredibly web specific. Routes can have logic and can define models, but they’re really doing that on behalf of the controller as a means of setting up initial state and state transitions.

I hope I didn’t make it more confusing in the process of trying to explain it. Also, lest the great Ember god Tomhuda or any of his Core disciples smite me, I officially genuflect 7 times and caveat that I’m still as fresh as anyone and I might be incorrect on any of this. Views are the last things any of us learn because you can get so much done without needing to know anything about how they work, but they are truly an absolutely mandatory part of the puzzle to unravel if you want to fight off a confusion/frustration aneurysm.

2 Likes

Actually that was quite clear, and could be used to fuel some discussions on how to improve Ember’s documentation.

OK, let me apologize first, I have a distorted view of MVC. I started programming on Apple, Trash 80s, and Main Frames all at the same time in '82 I was a procedural programmer for many years and back in '98-2000 I wrote responses to article printed in programming magazines at the time that said things like “this can only be done in an OO language”. I met many challenges doing what they said couldn’t be done in VB 3 and other procedural languages to the displeasure of the authors.

So I started this conversation with my bias JFrame/JDialog (Java) and Form (VB 6/VB.NET/C#) are the View, the controller was a class you wrote and wired all your events to (from the View). The model is databound to the View through Microsoft databinding or Heartbeat/polling in Java. Also the model is data transport through the application in the form of Business Objects, shunning Active Record as a pattern and preferring things like DataMapper to talk to the database. MVVM, basically changed binding of the Model to the View to binding the Controller to the View, and converted the Controller to a blind/testable/event driven/copy of the model object.

Like Ember we had a “router”, we called an Application Controller and later renamed to XMediator where X was the part of the application that mediator managed. Having the term controller at two tiers of the application design was confusing. An AppMediator was common as well as some specific business logic of the application, a ContractMediator. Mediators are the access to the business logic of the application and all MVC was good for was presentation of the application.

Workers and Dispatchers handled threaded tasks and the DataFacade, MachineFacade, and WebFacade simplifies access to the domains as the “facade” pattern name suggests.

So when I have used MVC for the last 15 years I have only used it as a UI pattern. Any business logic (or domain logic) is in the Business Tier of the application with Mediators being a façade like access to that layer.

Does anyone actually use Active Record as a pattern anymore?

By this do you mean the Controller handles the events generated by the View? Because I’ve never seen button on the Controller, but the event listener for the button should be on the controller.

Ah, so you’re saying that in Ember the event handler is in the View (the second programming logic version of the view, not the View that is rendered on the screen) and that as a developer you need to redirect that event to the Controller (because it is not automatic)?

Bingo- your view is capturing the swipe event or whatever, and sending it to an action on the controller that has some domain meaning to your application. You could attach a swipe event listener directly to your controller, but then your controller has to become DOM aware, which it shouldn’t be. Your view could also hold logic that only matters to the presentation, like opening/closing an accordion.

Implementation detail.