didInsertElement for only single element EmberJs - ember.js

I want to call didInsertElement on just one element but not on others, I have a component template with multiple elements, but I just want to use it on specific element.
Any Idea how to do this? Is it possible, if yes, good practice or not..and component having multiple elements pointing towards other components, is that okay?

Assuming I'm understanding you correctly and you want to call didinsertelement on one instance of a component, but not on the other instances of the component.
With that assumption the simplest approach would be to pass in some parameter to the component that states whether or not to execute the logic handled in the didinsertelement.
{{some-comp dologic='false'}}
setup: Ember.on ('didInsertElement', function (){
if (this.get ('dologic')) ....
})

Related

Ember js: How to increment a property in a controller while it is consumed in the template?

How to increment a property in a controller while it is consumed in the template?
Case : I will consume same component multiple times in a template and I want to calculate how many times I've used that component in my template and I also want which component(tracking each component) gets destroyed When I do some actions.
So what I thought was a give a specific number to each component and Track it down using its hooks by using a property which would increment each time I access the component
Note: If there is any other way to track each component among others, kindly post them too and Thanks...
Your case to find the number of times a component is used can be implemented using a service along with a component hook.
You'll need to create a service to maintain the count with an increment function and call the increment function from the init hook of the component.
So, the increment function will be called everytime a new instance of the component is created.
You can find a working example here

Access the instance of the component from parent component in EmberJS

I have a "container" component
# components/container-component.js
import Ember from 'ember';
export default Ember.Component.extend({
displayComponent: 'simple-box'
});
The template is
# templates/container-component.hbs
<div>
{{component displayComponent}}
</div>
Now, from within "container-component" instance. How can I access the computed "displayComponent" instance?
Any ideas on how I could go about it?
When I use the get method I get the string identification of the component
this.get('displayComponent')
# returns (String) 'simple-box'
There is not a built-in way of retrieving children components from the parent component's js file as far as I know. If you really want to achieve this, please refer to my twiddle I have prepared for you.
As you can see from the code; within the template parent passes itself to the child and child registers itself to the parent. Note that this is an illustration of code smell and this is something I never use in my projects.
Because, in my opinion what you are trying to achieve is a clear violation of many principles that ember is built upon. Why do you want to get the child property from the parent directly? You can register actions to child component and get notified for various events within the child component. Why do you need direct access? It is better for a component to be working independently by itself. In this kind of approach you are polluting parent's code with child component's internal design considerations. You can query DOM tree via jquery within parent but getting the child component instance created for you by Ember infrastructure is a sign that you are trying to design something that is out of Ember's approach. We can help you better if you post another question (or modify this one) to describe your intention. May be someone could lead you to a better design. Best Regards.

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.js input action get element

I'm sorry I couldn't figure out something so basic and had to ask here, but in the newUser callback function, how do I get a reference to that input element?
{{input action="newUser"}}
I tried param=this this.$() this.get('element') Nothing worked in Ember 1.7
You could try
this.$('input')
which will return a jQuery-style element set on which you can do more jQuery-type things, or
this.get('element').querySelector('input')
this.get('element') will return the view element, so you need to poke down into it to find the input element, whether by tagname as above, or via some other selection mechanism such as id or class.
However, this assumes the action is defined within the view, where this.$ and this.get('element') are defined. It will not work if the action is defined on the controller or route. It is a common Ember pattern to have an action handler on the view, which does view-related things, and then sends some action along to the controller for it to do controller-related things.
However, if you are trying to retrieve the input element just in order to muck with its value, then you can do this much more easily by simply modifying the property bound to the input elements' value.
You don't even need a reference to the element to clear it. Just use data-binding:
http://emberjs.jsbin.com/telat/1/edit

How can I have a component inherit several attributes from the controller?

New to Ember.js.
I'm trying to create robust components that will delegate to the controller for various attributes. I know that I can bind individual attributes like this, but it seems verbose.
{{#my-component attr1=attr1 attr2=attr2}}
Hello
{{/my-component}}
It seems like it might be a common case to want to delegate everything to the controller. Is there a recommended pattern for doing so?
Your example code would be considered the correct way.
You could technically pass in a single object (possibly composed from the controller), but I would recommend against that. A component shouldn't really know much about where the data is coming from as attr1 could be a model property and attr2 could be a property of the view which doing some sort of computation. By passing in the single object you limit the flexibility of the component.
In addition to flexibility I tend to prefer the long argument list as it is clear what your component accepts; even if it is a bit more verbose. If your component is taking a huge list of arguments it may be a sign that the component is trying to do too much and you may want to break it down into smaller components.
App.MyComponentComponent = Ember.Component.extend({
attr1: function() {
return this.get('targetObject.attr1');
}.property('targetObject.attr1'),
attr2: function() {
return this.get('targetObject.attr2');
}.property('targetObject.attr2')
});
From Ember docs:
"If the component is currently inserted into the DOM of a parent view, this property will point to the controller of the parent view."
Use with caution.