I'm looking for some clarification on views in Ember.js
Coming from a rails background and I'm trying to ignore any preconceptions. From what I understand of the ember framework there are 5 components:
As an example lets say I have a EventsController that has data loaded on the applicationRoute:
ScheduleApp.EventsController = Ember.ArrayController.extend();
ScheduleApp.ApplicationRoute = Ember.Route.extend({
setupController: function() {
this.controllerFor('events').set('content', ScheduleApp.Event.find());
}
});
Now in my template instead of iterating over each and displaying the information I want to iterate over each and create an associated view so I can add interactions to each event. I presume I would need to create a new view for each event and have it display in my template. However, I'm not sure where I create these views. Do I define a view class and then ember will create a new view object each time I call it using the view helper? Eventually I would like to use the appendTo on the view to inject my events to different places in the dom. Where would this be defined?
I've tried reading over the ember.js guide for views but it describes the context of a creating a single view. I think I want to make many views for each event and then dynamically interact with those objects.
Up to now ember has been outrageously clever so I would assume there is a built in method for generating these views. After all, most user interfaces are full of lists that require interactions. The problem is the list I'm trying to make I then want to spread over the dom depending on its attributes.
Ember. View is the class in Ember responsible for encapsulating templates of HTML content, combining templates with data to render as sections of a page's DOM, and registering and responding to user-initiated events.
Ember. js uses Handlebars, a lightweight templating engine also maintained by the Ember team. It has the usual templating logic, like if and else , loops and formatting helpers , that kind of stuff. Templates may be precompiled (if you want to cleanly organize them as separate .
What is Ember? Ember is a front-end framework for building web applications. It uses the MVC framework to serve data to views that update automatically as the underlying data changes. Ember makes building a responsive web application super easy.
Regardless of how the URL becomes set, the Ember router then maps the current URL to one or more route handlers. A route handler can do several things: It can render a template. It can load a model that is then available to the template.
As per your code, App.EventsController
has a list of events, now let us say we want the UI to have a list of events displayed and for each event say we want the view to have a delete button which deletes the event when the user clicks
One way to accomplish is by using Ember.CollectionView
, the collection view as the name suggests is tailored for these sort of requirements, in many Ember examples the usage of view is not defined because ember auto-generates it for you but in some cases we might need to explicitly define a view to meed our requirements
App.EventsView = Ember.CollectionView.extend({
// It needs a list of data to iterate upon
// We are binding it to the controllers content data which
// is a list of events
contentBinding: "controller.content",
appendSpan: function(){
view = Ember.View.create({tagName: 'span'});
this.get("childViews").forEach(function(child){
view.appendTo(child);
});
},
// Now we need to also define a view template that will be
// generated for all the elements in the content array
// This could in turn be another collection view if required
// I am going to keep it simple for now
itemViewClass: Ember.View.extend({
templateName: "event",
deleteEvent: function(){
// Implement Delete
this.get("content").deleteRecord();
},
notifyUser: function(){
// The record doesn't get deleted as soon as user clicks, the request goes to
// server and server deletes the record and sends back the response to the
// client, Hence I'm using an observer here on isDeleted property of the record
if(this.get('content.isDeleted')){
alert("Record deleted Successfully");
}
}.observes('content.isDeleted')
})
})
Important Note Inside the CollectionView definition this.get("content")
refers to the array of events, while in itemViewClass this.get("content")
refers to the single event object
//Defining the template
//Assuming the event model has a name property
<script type="text/x-handlebars" data-template-name="event">
Name: {{view.content.name}}
<a {{action deleteEvent target="view"}} href="#">Delete Event</a>
</script>
Now when you hit your application_url/events you'll a list of events each event has a delete button, I hope this clears some concepts
For more information about CollectionView
Update as per the comment:
If you want to append another view to each child view, you can do so by editing the template of itemViewClass as follows
<script type="text/x-handlebars" data-template-name="event">
Name: {{view.content.name}}
<a {{action deleteEvent target="view"}} href="#">Delete Event</a>
{{ view App.SomeOtherView }}
</script>
it can be a partial too as follows
<script type="text/x-handlebars" data-template-name="event">
Name: {{view.content.name}}
<a {{action deleteEvent target="view"}} href="#">Delete Event</a>
{{ partial "somePartial" }}
</script>
or if you want to do it programmatically say, you click a button in the EventsView template and on click all the childs view must have a span tag appended to it(I am very bad at giving examples)
//This is the template for App.EventsController,
//template-name = "events" => view is App.EventsView and controller App.EventsController
<script type="text/x-handlebars" data-template-name="events">
<a {{action appendSpan target="view"}} href="#"> Append </a>
</script>
appendSpan
is defined in the CollectionView
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With