Ember-CLI Resolver: Naming Convention Questions - ember.js

I am brand new to ember... working through the ember guides AND trying to apply that same knowledge through the ember-cli guides simultaneously.
I am noticing there there are a few big gaps in logic between the two when it comes to the ES6 Resolver and it is causing problems for me, particularly when i want to reference things like ApplicationRoute, ApplicationController, and the like.
I have to ask, for my own sanity, how to I define an ApplicationRoute or an ApplicationController? Are they saved as application.js or index.js?

ApplicationRoute would be saved under app/routes/application.js, ApplicationController would be saved as app/controllers/application.js.
as long as those files export default the proper subclassed Route or Controller, respectively, everything should be fine.

Related

ember 2.17: calling a jquery document.ready() function

I am really new to Ember, which I am asked to do and well, love to learn. Basically, the current project uses Gentelella Admin Dashboard. I being trying to get the dashboard to load properly but failed.
After I login, I get redirected to /dashboard/ route, which basically loads the main dashboard interface. Now the problem is I can't click-expand the menus on the sidebar nor toggle the sidebar menu. And the main page is not extended to fill the space, as in our current application.
I know the function init_start() takes care of the resize and the click, which is already added to vendor.js from custom.js but I can't seem to call the function from ember at all.
My latest attempt was using mixins but it failed too:
import Ember from 'ember';
export default Ember.Mixin.create({
activate: function() {
this._super();
init_sidebar();
}
});
then from dashboard.js route:
import HandleTempLoadMixin from '../mixins/handle-temp-load';
export default Route.extend(AuthenticatedRouteMixin,HandleTempLoadMixin, {
});
but still the function is not executed.
I have read that it is best to avoid working with jquery inside ember in SO but I have pretty much many JQuery functions that I cant transfer right now (nor sure why exactly since it says somewhere in the documentation jquery is built into ember itself).
Anyway, what is the best way to initailize the dashboard interface?
From my understanding you have some jQuery stuff that you would like to utilise. I suggest looking into Component's didInsertElement hook and triggering your custom code from there.
You can find more details in here https://guides.emberjs.com/v2.17.0/components/the-component-lifecycle/#toc_integrating-with-third-party-libraries-with-code-didinsertelement-code
In general, try avoid working with view related stuff in Routes. Ember's power comes from strong conventions. Learning where to place your code is crucial.

Ember.js Overriding an add-on's component

I am fairly new to Ember.js and trying to use the datepicker component from ember-cli-jquery module (https://www.npmjs.com/package/ember-cli-jquery-ui) in my project.
The issue I'm facing is that I need to run some custom jquery initialization code after the datepicker component loads.
After research for several hours, came across this article http://mavilein.github.io/javascript/2013/08/01/Ember-JS-After-Render-Event/ and this stackoverflow post: Using Ember.js, how do I run some JS after a view is rendered?
The post describes using 'didInsertElement' hook to run any initialization code - however, as I'm using the ember-cli-jquery-ui plugin, I'm not sure how to do this without changing/modifying the code in node_modules/ember-cli-jquery-ui/addon/mixins/jqui-widget.js
I looked at the source code for ember-cli-jquery-ui and it turns out the above mentioned method is already being overridden. Reading through the API documentation on emberjs, it seems like any method can be extended and classses can be re-opened, I'm just not sure how to do it.
Is there a way I can further extend/override that method in my app.js or index.js for instance?
Any help would be greatly appreciated.
You can just extend the component and call the super method. and use this as the new component in you app
//app/components/my-date-picker.js {{my-date-picker}}
import DatePicker from "path/to/picker"
export default DatePicker.extend({
didInsertElement:function(){
//do things before super
this._super(); //this._super() instead of this.super()
//do things after super
}
})

Create loading substate for application route

I'm trying to create a loading substate for the Application route using the new named substate options added recently, but for some reason, I can't get it to work. Originally, I just had created a simple template, loading.hbs, and it worked automatically, but because of the issues with substates on the application route, some of my UI was still visible. I'd like to correct this now.
I've tried renaming and moving the template around to the following places:
/templates/application_loading.hbs
/templates/application-loading.hbs
/templates/application/loading.hbs
None seem to work though. I don't need any custom routing behavior so the default generated route should do me, unless its a requirement for this to work. Documentation on this feature seems to be sparse. I found the jsbin for this feature and I should be doing it correctly according to it unless there's some issue with ember-cli.
Thank you for any assistance.
DEBUG: -------------------------------
DEBUG: Ember : 1.11.1
DEBUG: Ember Data : 1.0.0-beta.16.1
DEBUG: jQuery : 1.11.2
DEBUG: -------------------------------
I believe that loading.hbs and error.hbs are the application's loading and error substates. Your application-loading.hbs doesn't exist to Ember, which is why it's not working.
As for the additional UI elements: I believe the rest of application.hbs is going to render regardless, so the only suggestion I would have is to nest all those elements one level deeper. It sounds like a big ordeal, but it's actually not that bad:
In router.js:
this.resource('whatever', {path: '/'} function() {
// All your existing routes
});
Then rename application.hbs to whatever.hbs and change application.hbs to just have {{outlet}} in it. This should really change very little else in practice, but it will keep the rest of your UI elements from rendering until loading is complete.
Really should've google it before adding the bounty.
Evidently, this feature is broken. There's a fix already though, just needs to be merged and released.
It looks like you must have a moduleBasedResolver
https://github.com/emberjs/ember.js/blob/06e41ad7ccd28558dd4e651aa070bc06f7757821/packages/ember-application/lib/system/application-instance.js#L153
https://github.com/emberjs/ember.js/blob/b80d66f71d75ad0db9022438ed58a41ac84f45f5/packages/ember-routing/lib/system/router.js#L79
When I look at this value in an ember-cli app it's undefined. Which seems odd because ember-cli is es6 module based.
Then I found this https://github.com/emberjs/ember.js/issues/10756 looks like you can add a route application-loading or hack in moduleBasedResolver onto the registry as a temporary solution.
and
https://github.com/emberjs/ember.js/pull/10944
should fix the issue in the longer term.
It appears you already found this, it did not appear loaded when I wrote this answer. Sorry for the noise.

When to use which controller type?

I seem to be getting more and more confounded at what appears, on the surface at least to be pretty basic architectural questions regarding building ember apps.
Which Controller type?
In the last month or so, I've seen people implement controllers through Ember.Controller, Ember.ArrayController, Ember.ObjectController, and Ember.ArrayProxy. Removing ArrayController and ArrayProxy (due to them being identical), what are common use cases between each type?
So far, i've been able to gather that:
ArrayControllers/Proxies should be used when you have n elements within the view you intend to control
ObjectControllers should be used when the view is simple enough to maintain it's state in a single object, or be a single instance of a model's object.
Controllers --- ? No idea.
What are some basic differences between the controller types? There doesn't seem to be concrete information on when to use which, and for which use case. The API docs are good at telling me the nitty gritty of each of them, but not WHEN to use each.
The relationship between a View and a Controller can be baffling
When a View is connected via a routes ConnectOutlets function call, what exactly happens between the controller and the view?
Are events tied into the view itself (which seems to be the case) and if so, where on earth do you interact with the controller singleton to perform CRUD-esq things on its properties? this.get('controllerName') doesn't seem to do the trick, and nearly each post or tutorial or code sample out there does this a different way.
Models that aren't
I realize that Ember Data looks to help solve some of the more irritating parts of dealing with data and keeping it in sync, but at a larger perspective, in the concept of "MVC", ember doesn't really seem to have a Model of any kind. It's just some object that gets subclassed from a specific thing and then tracked....somewhere? Somehow? Magical?
#trek sufficed that an Ember.Object could manage ajax'ing data and handling state on the client just fine, but if you look at something like the todomvc.com ember app, it uses a localStorage paradigm that is COMPLETELY different in implementation then everything i've looked at.
How EXACTLY should the 'Model' part of the MVC equation be done here?
Views make me want to murder children
There seems to be a significant number of ways to construct a "view" in terms of displaying markup to a user.
ContainerViews, using subviews / childviews
nested outlets
Handlebars templates + an outlet
using #each foo in controller
Injection through literals (template: Ember.Handlebars.compile('<h1>foo</h1>') etc)
With that in mind, what's the 'proper' way to build modular UI components with ember? This more than anything is a major pain point for the adoption of this framework for me.
I love the direction that Ember is going with application development on the web. The concepts seem simple, but the verbosity is that of Objective-C (which makes sense given it's lineage) but I swear to god I feel like i'm fighting the god damned framework more than i'm actually working on my application. The verbosity of the syntax and the lack of structured documentation outside of API documentation (which lets face it, 300k of javascript is a significant amount of code to throw some breakpoints down and try to debug your issues).
I realize the challenge that you guys are up against, but hopefully this at least makes you pause for a minute and think of how you could make life easier for the incoming developer who's worked with other frameworks (or hell, even worked within an MVC framework, like rails or django or backbone or angular) and say "this is how we think ember should be used".
Take some of the opinionated software design decisions and apply them toward the community. We'll do nothing but be cheerleaders for you if you do it, promise.
Please don't hurt any children. AFAIK the ember-core team are all over 18, so any ember-view-related frustration is clearly better directed towards adults. With that in mind...
Which Controller Type?
You've got the "what" right, but maybe missing the "why". Controller can be a little misleading, especially coming from rails. Think of these controller singletons as representing the state (in-memory) of your application.
Which kind of controller to use depends on what is required for that part of your application. For example, a back-of-napkin sketch for any app might have a topnav, postList, postDetails section. In ember, each is represented by one or more view/controller pairs. In this app I would expect to see ApplicationController and NavigationController extending Ember.Controler while postList would extend ArrayController and PostDetails would be an ObjectController.
You could do it all using just Ember.Controller but ObjectController and ArrayController are really useful for wrapping model data. Any non-trivial ember app will probably use all three.
The relationship between a View and a Controller
A controller's job is to provide the context in which the view will be rendered. Ideally you'd like to keep logic out of views, so a typical controller will have lots of computed properties to do things like:
transform data from the underlying model objects
sort/filter/select a list of objects
reflect application state
whats the deal with connectOutlets? This is where you should be using the requested route/context to decide which views/data should be plugged into the outlets of your application. The controller's connectOutlet method has a bunch of magic to make it easy, but maybe too much magic. What happens (afaik) when you call: parentcontroller.connectOutlet 'child' is
Ember creates an instance of ChildView
The {{outlet}} handlebars helper in parentController's view is bound to this childView instance
The childView is rendered with the router.childController singleton as it's context
where to do crud stuff?: Typically in an action on the router. This seems crazy at first. Think of ember router not like rails but as a stateManager that just happens to also handle routing. In near-future router API will change to make this more clear. Anyway, use router actions to do things like create model instances, commit/rollback transactions and trigger state change. This is easy to do if you use the handlebars {{action}} helper for links/buttons as it targets the router by default.
Views on the other hand should have logic for "reacting to browser events" - that means really low-level stuff like show/hide something on mouseover or integrate with 3rd party libraries to do effects and animations.
You might find this screencast helpful in understanding how to do CRUD-esq things:
http://blog.bigbinary.com/2012/09/06/crud-application-in-emberjs.html
Models WTF?
Agreed in Ember any object could be used as a 'Model'. I think #trek does a good job of demonstrating how one might accomplish this via Ember.Object. This works great for a simple app, and six months back maybe would've been your best bet as ember-data was really immature. I'm not clear on the history of ember's todomvc app, but for sure it was written months ago. For sure it should be updated, but meantime I'd not recommend using it to learn about current ember best-practices.
Instead, you should go with ember-data. Over the last few months it has really evolved and should be the default choice for any new, non-trivial ember app. #tomdale just gave a great presentation on this topic, I'd recommend having a look: https://speakerdeck.com/tomdale/ember-data-internals
what's the 'proper' way to build modular UI components with ember?
For building modular UI components:
ContainerViews, using subviews / childviews
Injection through literals (template: Ember.Handlebars.compile ...)
For building an individual application:
nested outlets
Handlebars templates + an outlet
using #each foo in controller
Building modular UI components is a totally different problem than building an application. Ember.View and it's subclasses were designed for this purpose. You can easily extend/combine them to compose widgets with custom behaviors and share those widgets across applications.
At least that's how i've seen it done. If they are for internal use could also reference handlebars templates instead of object literals, but if planning to distribute the object literals approach seems best.
A great real-world example of this is the ember-bootstrap project. I learned a lot about working with ember-views by reading through that project's source. http://emberjs-addons.github.com/ember-bootstrap/
TLDR
Pick controller that maps to type of data being represented
Controllers provide context for the view and remember application state
Use ember data for your models
Use subclasses of Ember.View to make components
Be nice to children

Do I have to explicitly create an `ApplicationView` and an `ApplicationController` for every Ember.js application?

From Trek's tutorial:
Your application must have an ApplicationView property. An instance of
this class will be created for you and inserted into the application's
view hierarchy as the root view.
And the tutorial gives this example code:
App.ApplicationView = Ember.View.extend({
templateName: 'application'
});
App.ApplicationController = Ember.Controller.extend();
What is special about ApplicationView and ApplicationController? Is their particular name reserved and must be used by conversion or is there something special about the way the router refers to them?
As I understand it, one of Ember's principals is to eliminate boilerplate code. So I am guessing there is something more to explicitly creating these two views for every app as starting point -- otherwise Ember would just make them for me behind the scene.
To rephrase my question, what makes ApplicationView and ApplicationController special in an Ember application. Do I need to create them explicitly for every app and if so, do I need to name them following a convention?
Note: I am using ember-latest
Ember.js tries to adhere to the programming philosophy of convention over configuration. Because of this some things need to be specifically named and follow correct casing rules. Upon calling App.initialize() your application looks for the property on itself App.ApplicationView. Your app then renders this view, inserts it into the dom and auto-creates an instance of App.ApplicationController, setting it as the render context for your ApplicationView. This means that any properties in your ApplictationController can be bound in your ApplicationView simply by referencing them in the view.
If you call App.initialize() with out an App.ApplicationView or App.ApplicationController ember will throw an error letting you know you must create them.
ApplicationView and ApplicationController are integral parts of your ember application and must exist. Ember is an MVC framework, ApplicationView is your root V, ApplicationController is your root C. It can be tempting to try to use frameworks like ember for just the pieces that you want, but with just a little more work you'll have a much more robust, and easy to use application that trying to cherry pick functionality.