Why this.$ is not available in Ember Controller - ember.js

Ember.$ is available in the controller whereas this.$ is not. But it is available in components.
Ember.$(".loading-splash").hide(); is working on controller where as
this.$(".loading-splash").hide(); is throwing an exception "this.$() is unavailable"

Ember components have a this.element, a place in the DOM to which they are attached. Older versions of Ember, 3.x and below, wrap this element with a this.$() so that you can conveniently use JQuery with that element as a context.
For example, this.$('.some-class') will locate elements with some-class within the scope of the component, i.e. within the component's element. Ember.$('.some-class') will locate elements with some-class anywhere in the page.
JQuery integration was made an optional feature in Ember 3.4, was no longer enabled by default in 3.14, and finally deprecated late in 3.x cycle and removed in Ember 4.0.
Controllers and Glimmer components are not associated with an element in the DOM, so there is not this.element to wrap.

Related

application view/component in ember-cli 2.13

I have recently started a new project with the most recent ember-cli (v 2.13 as stated in the topic). I am rather set on generating clean semantic html, and as such don't like the extra div.ember-view that the application generates.
Before I could create the app/views/application.js file with following content:
import Ember from 'ember';
export default Ember.Component.extend({
tagName: ''
});
It simply used the component as application view and got rid of the root tag, however it doesn't seem to work anymore. In fact when debugging the resolver "view:application" doesn't show up at all. Is there a new way of solving this situation? Afaik routable components are not exactly in yet, are they?
Granted, my last ember project was using ember-rails (with ember 2.7), now I'm going for a pure ember-cli project, so a few things might indeed have changed.
How can the same effect be achieved now? Is it just a case of adding a special rule to resolver? Or maybe it can be reached otherwise? I learned that ember docs can be rather lacking when it comes to new obscure features...
Views are removed from the Ember 2.0 API. Have a look at this deprecation https://emberjs.com/deprecations/v1.x/#toc_ember-view.
Regarding your question, you can find related discussions in the below url.
https://github.com/emberjs/ember.js/issues/11486
Implementing tagName: '' is not suggested one. In current situation, you can't remove that extra div created by ember application, since ember needs that. What you can do is, you can just apply CSS style to mitigate this,
:root,
.ember-application,
.ember-application>div {
height: 100%;
}
Views are deprecated in Ember > 2.0. The components do generate a div with div.ember-view class added. You can give custom classes to that component using the classNames property and for the component to be other than a div, specify the element to the tagName property.
The extra div can be eliminated using tagName: " " inside each component but you cannot use this.$() to access the component element. The only option is to customize the div created according to our needs.
For application template, I don't think there is any hack to eliminate the extra div created. It might be required by the eventDispatcher.

What Component? A property of $SOMEOUTLET was modified inside the didInsertElement hook

I have an app with a number of components on the page. I'd really like to know what component a given deprecation is related to. Is there a way to map an outlet to a component?
In other words if I get:
A property of <frontend#view:-outlet::ember673> was modified inside
the didInsertElement hook. You should never change properties on
components, services or models during didInsertElement because it
causes significant performance degradation.
What component is being used for ember673 ?

Understanding and using Ember Component lifecycle hooks

I'm trying to figure out why an Ember component is not working (and trying to learn about component lifecycles in the process). The component in question is Ember-cli-mapbox. It uses nested components. You can have a mapbox-map component, and within that component you can have several mapbox-marker components. Now, how it is supposed to work, is the mapbox-map component initialises the map, and then passes a block to the child marker components. The child marker components then references the map that got passed down to them. An example of the components in use (which come from the component docs):
{{#mapbox-map mapId='ember-cli-mapbox.7c3914f2' as |map|}}
{{#each positions as |position|}}
{{mapbox-marker map=map coordinates=position.coordinates}}
{{/each}}
{{/mapbox-map}}
Now, the components get set up using the didInsertElement hook, which makes sense to me since the DOM needs to be in place before the mapbox-map component can bind to a element in the dom. It doesn't work like that though. The didInsertElement of the child components get executed before the didInsertElement hook in the parent component. So, the marker tries to reference the map before it was created. I figured this out by putting console.logs in the component init code. I can't find much documentation on component lifecycles. didInsertElement does get referenced in the API docs here, but it seems that the newest API docs are actually out of date and don't reference a bunch of other hooks described here. The latter link says that life cycle events happen in the following order:
didInitAttrs
didReceiveAttrs
willRender
didInsertElement
didRender
Now, things get weird. When I replace didInsertElement in the components with didInitAttrs, it fires in the correct order. The didInitAttrs hook on the parent component fires first, followed by the child component didInitAttrs hooks. Problem with this is, the DOM isn't ready yet, so it doesn't help much. I also can't put the map binding event in the Ember runloop, since it need to be returned and passed as a block to the child elements.
So, my questions are:
Why, when using didInsertElement on components, do the hooks get executed in the order they do? (children, then parents)
How did this component ever work in the way it's currently written?
Am I supposed to use the above mentioned hooks if they're not mentioned in the official API docs?
I've recreated the addon in an Ember Twiddle here. Child hooks get called before the parent hooks, causing the component to break since map is undefined when the hook is called. This happens on Ember 1.13.8 as well as 1.13.9.
Why, when using didInsertElement on components, do the hooks get
executed in the order they do? (children, then parents)
This was changed in version 1.8. It was previously parent, then children but this often required people to use some complicated method of waiting for children to render to do certain things. Changing the order made learning Ember simpler.
See https://github.com/emberjs/ember.js/issues/5631 for more information.
How did this component ever work in the way it's currently written?
I have not used this addon, and have no idea if it works or not. I fixed your twiddle to work, however: http://ember-twiddle.com/4c3e55d0a66ead378bdf
Am I supposed to use the above mentioned hooks if they're not
mentioned in the official API docs?
These hooks are not mentioned because the documentation is still catching up to changes in Ember. Feel free to use them if you'd like.

Ember Handlebars link-to vs linkTo

When you look at a lot of the older (Pre 1.0) Ember code, it seems like the Handlebars helper is {{#linkTo}} (see, for example this SO post from January 2013). Now, the method seems to be {{#link-to}}, based on the official Ember docs.
I can't find any mention of when the helper method changed. But I just tried both {{#link-to}} and {{#linkTo}} in an app using Ember 1.2 and Handlebars 1.1.2 and both work as expected.
Two questions. When did this change occur? I can't find any mention of it in Handlebars changelogs or anything that mentions it. And 2, I assume that since {{#link-to}} is what's currently in the docs, that's the new way. But there's no deprecation notice. Is there a plan to no longer support {{#linkTo}}? If so, when? Which Ember/Handlebars version? For bonus points, link to a an article that talks about that rationale behind this decision.
You wouldn't find anything about link-to in the changelog for Handlebars since it's a helper class for Ember and not included in the main Handlebars library.
According to the blog post for RC8 the old syntax has been "soft deprecated". The old method is marked with #deprecated in the source but doesn't log anything even if used (not even with Ember.ENV.RAISE_ON_DEPRECATION set).
You will also see there that the old one is kept as a straight alias to the new one with no real implementation of it's own.
Ember.Handlebars.registerHelper('linkTo', Ember.Handlebars.helpers['link-to']);
Since they plan to use semantic versioning (as said in the post for the 1.0 release) for their releases they can't really remove this helper until they hit 2.0 though.
The linkTo and bindAttr are changed to link-to and bind-attr in this pull request. The hyphenated form was used, because is more close to web components custom elements syntax. So use the hyphenated form if avaliable in your current version.

Cannot read property 'container' of null when using linkTo helper in an Ember template

I am creating an Ember application as an add-on to some HTML returned from the server. I need this HTML so that the site can be indexed by search engines, and also to speed up the initial page rendering for the users.
So my application consists of several Ember Views, appended to different DOM elements of the HTML generated by the server. I don't use master templates for routes, so I set renderTemplate function of each route to do nothing.
My Ember App is bound to body element and I can successfully append a custom view to an element down the tree. It works:
In this JSFiddle three last elements of the list are appended by Ember
But when I try to use linkTo helper in my template, I hit an error:
Uncaught TypeError: Cannot read property 'container' of null ember-latest.js:32224
which is in this function:
router: Ember.computed(function() {
return get(this, 'controller').container.lookup('router:main');
}),
In this JS fiddle I just add linkTo to the template, and it breaks everything
In general, can Ember work this way - having many Views scattered
over the HTML rendered by the server?
How can the example code be
fixed?
I've fixed your fiddle here, Check it out.
Seems like you are starter to Ember,
So here are some tips for you,
You should have an application template, which will be the root template and on which all the templates will be rendered.
You shouldn't access views using this.container.lookup, that is for debugging only.
You shouldn't append views to the DOM, it's the job of the framework to do.
By default your application will be appended to the body of the html, if you want it to be appended elsewhere, give the rootElement property when creating the application. Refer here for configuring your application.
The rootElement can be either a DOM element or a jQuery-compatible selector string. Note that views appended to the DOM outside the root element will not receive events. If you specify a custom root element, make sure you only append views inside it!
Don't access any controllers globally like App.itemsController.set("content", model), if you want to access another controller inside a route, use this.controllerFor, and to access inside another controller, use needs.
You need not create any controller instance like App.itemsController=Ember.ArrayController.extend({}).create();
The framework will take care of all these.
I found that I need to additionally bind the view and the container together to make this fiddle work
App.itemsView.set("controller", App.itemsController);
App.itemsController.set("container", this.container);
So the resulting working code snippet is here:
http://jsfiddle.net/ddegtyarev/6cBRx/6/
Again, let me reiterate that I'm building an hybrid Ember application - i.e. I have some HTML returned right from the server, and some appended by multiple Ember views in multiple places. This is why I have to manually create the views and bind them with controllers etc.