as you can see, hbs has a placeholder for {{abcd}} and route returns the value for abcd but my page does not show that data. When i do a view source, i can see that js function is carried into the page! Am I missing something? do I need to write something in controller folder before route and model/template can talk to each other?
Templates don't know anything about route properties. {{abcd}} would refer to a controller property. In order to access it you will have to go through the controller's model property {{model.abcd}}.
I would recommend you give the guides a thorough look.
Related
I have inherited a codebase and trying to make sense of what is what. In emberjs application how do I know which controller (js) corresponds to a view (hbs) on a particular page. Is there a setting? Is there a convention?
The convention is that their names (or more accurately their paths) should be the same.
As in, controllers/page.js should have a templates/page.hbs and a routes/page.js
You can see this convention if you create a new Ember project using ember new or ember twiddle.
You can also specify the template name within a route using the templateName property.
// routes/page.js
import Route from '#ember/routing/route';
export default Route.extend({
templateName: 'something/different'
});
Ember also allows us to use the renderTemplate hook within our routes and pick a different template and/or a different controller.
// routes/page.js
export default Route.extend({
renderTemplate(controller, model) {
// Render the `something/else` template
// and use the and `other/thing` controller
this.render('something/else', {
controller: this.controllerFor('other/thing')
});
}
});
Read more in "Ember JS Guides: Rendering a template"
Ember also used to allow embedding templates within other templates using the partial helper.
It would matter a lot which Ember version you are using because that would restrict your concerns to a certain API behavior, since Ember did change a lot through the years.
For the most part it's pretty simple. Ember follows convention over configuration so let's learn the convention. The algorithm is as follows.
Look at the current url that you are on. In this case, we are on /foo
Open up the router.js file and find the route that matches this url pattern. If you don't specify paths then the url will just be the name of the route, but you could also be dealing with nested routes. Let's say we found route named foo.js which would be under appName/routes/foo.js.
Open the route file. Routes jobs are to fetch data in the model hooks, and then to set the variables on the corresponding controller instance via the setupController(controller, model) hook. When not specified, this method just sets the entire model object on the controller. Now we should have a decent idea of what variables have been dynamically set on the controller.
Open the controller under appName/controllers/foo.js. The best way to think about controllers is they are the single source of state for the corresponding template (appName/templates/foo.hbs). Their values are set via hooks on the route, as well as through the init method, computed properties, observers, etc. When you reference any {{variable}} in a handlebars template, the controller that matches this portion of the page's context is the source of state that resolves this variable. If the controller isn't defined, then Ember autogenerates one for you. Worth noting that controllers are singletons and their state persists between route changes.
Open the template.hbs file to see your markup. You might have components (custom html-looking tags that take attrs) which store their javascript under appName/components/component-name.js and their templates in appName/templates/components/component-name.hbs or have no template if the javascript file can just specify a tagName and that's it.
One other quick thing: routes are invoked in a parent/child hierarchy and correspond to urls via the route. The top level route is the application route. If you look in it's template, you will find an {{outlet}} Ember will then find whatever child route comes next and render its template into this outlet. by default /, the index route's template is rendered. But if the url was /foo then foo.hbs will be rendered into the application's outlet. Foo.hbs can have an outlet, and thats when we start getting into nested routes. That's about as quick/high level overview as I can give, ask any questions if you want specifics (I love Ember)
Please take a look at this JSBin1. I am using the same template for both the render in the index template and manually rendered in the renderTemplate function of the ColorsRoute. Clicking the More Colors link does not render the list of colors I return in the ColorsRoute model hook. Now, if you change the render 'colors-list model to render colors-list2 model, as I have done here, everything works as I would expect it to. The only difference between the two is that in JSBin1, I am only using the colors-list template, but in the second working example, I have one template for the render and an identical, differently named template for the ColorsRoute.
The code example, while trivial in the JSBin, is an exact extraction of something I am doing in a much larger application. This application has a bunch of widgets, which I represent by multiple named outlets in the same templates. I manually render into these outlets, as I do in the JSBin in the ColorsRoute renderTemplate hook. I do the manually rendering so that when certain events happen, I have actions defined on the route that will allow me to dynamically replace the contents of the outlet after making an ajax call to a REST API.
What is the explanation for this kind of behavior?
It's more related to the controller that's being created, not the template. And technically I'd say it shouldn't work on either, but it appears there's some route where if you don't define a controller, and that type of controller hasn't been created, create it, and use the current controller/model as the model backing it.
Really you should be providing a controller when using render if you're expecting it to have that controller as the backing controller.
renderTemplate: function(controller, model){
this.render();
this.render('color-list', {
outlet: "named",
into: 'colors',
controller: controller
});
}
http://emberjs.jsbin.com/cevagocekofu/3/edit
I have a route that looks like this:
#.route 'dailyTotal',
path: '/report/:year/:month/:day'
template: 'dailyTotal'
layoutTemplate: 'report'
data: ()-> this.params
And in my controller something like this:
Template.dailyTotal.bevTable = ->
params = this
# a whole bunch more...
In the controller, I use those params to do some rather complicated stuff that isnt' relevant to my question because this doesn't re-render (or execute?) when you navigate from one dynamic route to another.
For example, if I navigate from "/report/2014/05/21" to "/report/2014/05/22" nothing happens. That route only executes if you come from a completely different route (say, "/report/totals" for example).
When I put a break point in the controller it never gets this, but I see the params change within the data function. My gut tells me I need to somehow force the controller action to run, but it isn't obvious from either the IronRouter or Meteor docs. Any suggestions?
I tried to reproduce your issue by creating simple meteor app with route you published above, but no luck, IronRouter properly handles this case.
Please compare your code with :
https://github.com/parhelium/meteo-so-ironrouter-dynamic-routes
IronRouter properly detects change of params in the same route, so going first to /report/2014/05/21 and then to /report/2014/05/21 re-renders template properly.
App structure was generated using em tool, it generated a lot of dirs and files, but only few are important in this situation:
both/router/routes.js
client/controllers/report.js
client/views/report/*
Update
When you pass this.params through data field in controller then usage in template for your route is:
{{year}}/{{month}}/{{day}}
I am new to Ember.js and am trying to figure out how to piece things together at this point. One component I built, since I need a re-usable "widget" to use across many portions of my application, is a "site nav" widget. Basically, it's almost like the buttons/links you see in StackOverflow when you open a new question titled: "Questions Tags Users Badges Unanswered". In my app, these links have a name and id associated with them on the server-side. I want to be able to use this navigation widget on multiple parts of my app and it should be as simple as putting:
{{site-nav}}
into a template. I got that part working just fine, but the navigation is currently hard coded in handlebars. My question is, for a component, where is the right place to retrieve/populate model data from the server? For a controller, we do it directly from the controller's route definition. The component is not associated with a router. In fact, it can be re-used, as mentioned before, in several parts of the app.
I want to be able to drop this component into templates and have it populated with modeled nav from the server which has the name/IDs of the navigation I need. Where is the best place to do this? I'm guessing I'll still extend from something like DS.Model, but I'm not entirely sure where/when/how to integrate this with the component. When do I create the model and invoke a .find() type call to the server to populate site-nav with data?
you can pass value to component Passing properties to component
via handlebars.
{{my-nav navlist=listfromserver}}
so the list from server is in our controller can be passed to the component
I heard of mvc in javascript many times,however I have no idea about how the mvc work in js.
Since I have used the goolge map v3,and I found the MVCObject.
It seems that this is a helper class used for register and listener the property chang event of the object.
I thinks this should be the "Model", Howver I have not found the "MVCView" there.
I am really confused with that.
Anyone can give me more details?
In javascript the view is mostly some html template that is rendered by some view class in js. The model is a class that is bound to that view so that, when it renders, the data from that model is being loaded on the correct positions in the templates. Take a look at backbone.js for example.
Here's a brief overview at a high level on how the MVC Pattern works:
Controller:
Listens on some kind of interaction/event stream.
Controller can send the model that type of interaction/event.
Controller can also communicate with the the view.
Model:
Models will listen in on the interaction/event from the controller.
Is an abstraction of a data source.
Handles data logic and manipulation.
After it is done with logic, it then sends to controller which will then communicate with the view.
View:
View can communicate with the controller.
Knows how to render data from the Model to the browser visually.
The Controller tells to View to do something with something from the
Model.
A couple of things to note is that models can't communicate with views directly and vise versa. Only the controller can communicate with the view and model, so the controller acts as the delegator for the interaction/event retrieved from users interaction on the browser.