I have this code in my index.hbs file:
<button {{action 'showHotspots'}} class="btn btn-success padding">{{hotspotCategory.name}}</button>
I have the showHotspots method in my routes/index.js file:
showHotspots: function( selection ) {
this.toggleProperty( 'idFromButton' );
}
The method should toggle this part in my routes/index.js:
{{#if idFromButton}}
<p>Test1</p>
{{/if}}
However this is not working, when I do it as a component it works but I need the Test1 on a specific place on my page (below all the generated buttons). When I do it in components the Test1 gets displayed between the buttons.
Instead of working with a component I want to do this in my index.js file so I can control the structure of the page.
In short: on my index.hbs i have a if-statement that checks if a variable is true. I want to set this variable from my routes/index.js file (or from somewhere else, doesn't matter really) using a method that is called in either the same index.hbs file or from a component-1.hbs file.
if i understand the question , you using component, you should use method "showHotspots" on the actions of your component, if not you should use this method on the actions of your controller.
it's better to describe more about your question.
edit: if you using old version of ember js, this is an example
//#### controller index.js
App.IndexController = Ember.Controller.extend({
idFromButton: false,
actions: {
showHotspots: function( selection ) {
this.toggleProperty( 'idFromButton' );
}
}
});
//#### index.hbs (your index controller template)
<button {{action 'showHotspots'}} class="btn btn-success padding">some text</button>
{{#if idFromButton}}
<p>Test1</p>
{{/if}}
The (simple) solution was:
this.controller.toggleProperty( 'idFromButton' );
Related
I try to create a custom component for my application with emberJS, I have followed the quickstart tutoriel and now I try to create a upload button as a component.
It seems I don't have code issues but my component don't render on my main page. I have use the ember component generator to create it
here my upload-button.hbs :
<button type="button">{{#buttonText}}</button>
now my upload-button.js :
import Component from '#ember/component';
export default Component.extend({
actions: {
showExplorer(){
alert()
}
}
});
for the moment I simply put a alert() method in showExplorer()
and now my main page, application.hbs :
<upload-button #buttonText="Uploader un fichier" {{action "showExplorer"}}/>
{{outlet}}
I expect to see my button but I just have a blank page with no code error.
I suspect that's a really stupid mistake but I can't find it.
Glad you decided to try out Ember.js :) Your upload-button.hbs and upload-button.js file looks good. However, there are a couple of issues here.
The component, when invoked using the angle-bracket syntax (<... />), the name should be CamelCased to distinguish between HTML tags and Ember components. Hence, we need to invoke the upload-button component as <UploadButton />.
You defined your action, showExplorer, inside the component (upload-button.js) file, but, referenced in the application.hbs file. The data in the backing component file can only be accessed inside the component's .hbs file because of the isolated nature of the component architecture. Also, we can only attach an action using {{action}} modifier to a DOM element and not to the component itself. So,
we need to remove the action binding from application.hbs file,
{{!-- application.hbs --}}
<UploadButton #buttonText="Uploader un fichier"/>
and add the same inside the upload-button.hbs file:
{{!-- upload-button.hbs --}}
<button type="button" {{action "showExplorer"}}>{{#buttonText}}</button>
A working model can be found in this CodeSandbox
Hope you find learning Ember, a fun process!
I am using ember js of version 2.10 And i am trying to send data from component to route.
Here is my component template
<div class="pull-right search-section">
<form class="form-inline search-box" {{action save on="submit"}}>
<button type="submit" class="btn"><i class="glyphicon glyphicon-search"></i></button>
<div class="form-group">
{{input value=search class="form-control" placeholder="Search anything"}}
</div>
</form>
Advance Search
</div>
Now I am trying to send data to route from component js file with following code
import Ember from 'ember';
export default Ember.Component.extend({
save: function () {
var search = this.get('search');
console.log(this.sendAction('saveAction',search));
}
});
And trying to get at route js file with following code
import Ember from 'ember';
export default Ember.Route.extend({
actions: {
saveAction: function(search_string){
alert('fhdishf');
}
}
});
But unfortunately did not getting anything.
Thanks in advance.
You can send the action to the routes controller which then bubbles to the route if the controller does not define the action.
// Component in Template
{{task-item content=task tasksController=this}}
// Component Action
actions: {
copyTask: function(){
this.get('tasksController').send('your-action');
}
}
Inside your template file,
{{task-item
data=model
innerActionName=outterActionName
}}
The ember way of doing things is Data down, Action up. To pass the data back to the controller/router, you have to make it call the upper action (from controller/router)
Inside your component JavaScript file,
actions: {
componentActionName(param) {
this.sendAction("innerActionName", param);
}
}
componentActionName is what you need to put inside your template file which triggers the function defined inside component JS file.
Inside your component HBS file,
<div {{action "componentActionName" param}}>{{param}}</div>
{{action "componentActionName" param}}, is how you can pass the parameter back to component, and then controller/route.
One more thing
A component should be isolated, which means a simple component should not aware the surrounding environment. It only knows the data passed into it and can only perform data manipulation by passing the action and paramter to the right place (the route).
I have created template and controller both called navbar. The code that i have in controller is simply
import Ember from 'ember';
export default Ember.Controller.extend({
isLogged: true,
});
and that in template is
{{#if isLogged}}
{{#link-to 'login' class="uk-button uk-button-danger"}}Login{{/link-to}}
{{#link-to 'signup' class="uk-button uk-button-danger"}}Join now{{/link-to}}
{{else}}
{{#link-to 'dashboard' class="uk-button uk-button-danger"}}Dashboard{{/link-to}}
{{/if}}
<button class="uk-button uk-button-large uk-button-primary uk-width-1-1" disabled={{isLogged}}>Test button</button>
The same does not seem to be working. Am i going wrong somewhere ?
The template and controller were generated using ember generator itself and the code above is the only modifications that i made.
EDIT:
Exploring the documentation, i noticed that the name of controller should be same as defined in route. Now navbar is only a template which i import using partial is there any workaround i might use for the same ?
You should use a component for this.
Use {{partial}} only if you want to render a template in the current context. Use it only if your .hbs files became to big, but use it rarely. Often a component is the better choice.
Also there you should almost never use {{render}}. You can almost always refactor it to a component.
Also using {{render}} with a model param is deprecated.
The problem was that 'partial' will only provide the template not the controllers. The correct way for this would be to use render which will import views and controllers also.
I have an ember application which works fine. But user's interaction does some DOM insertion like below...
$(.test).append(<a {{action "getData"}}>Get Data</a>);
The problem is that Ember seems do not recognize that an action "getData" has been added to the DOM. Nothing is happening when I click the element. Any thoughts on this?
Another way I am trying to do is:
//create the element
$(.test).append(<a id="idnum">Get Data</a>);
//make click listener
$('#idnum').click(function(){
console.log("get data");
}
my question is where should i place the code inside the component so the it can listen on the click event. Thanks.
You should do it in Ember way. Try handlebars {{#if}} helper to render an element dynamically.
{{#if canGetData}}
<a {{action "getData"}}>Get Data</a>
{{/if}}
Here you can set the value of the canGetData to true in the controller based on the users action.
The first example can't work because ember does not analythe the Handlebars elements in the DOM, but rather parses your Handlebars template with HTMLBars, which is a full HTML parser, and then renders it manually by inserting elements, not text into the DOM.
However the second example is the way to go if you have to rely on external code that does manual DOM manipulation. And it does work. Checkout this twiddle.
This does work:
this.$('.target').append('<a id="idnum">Get Data</a>');
this.$('#idnum').on('click', () => {
alert('clicked');
});
Just make sure that the DOM is ready. So do it in the didInsertElement hook or after the user clicked a button or so.
Like Lux suggested avoid DOM manipulation. I prefer the following approach,
if it is dynamic then you can consider wrapping DOM element as a new component and use component helper.
find sample twiddle
In application.js
export default Ember.Controller.extend({
appName: 'Ember Twiddle',
linksArray:[ Ember.Object.create({value:'Text to display',routename:'home'}),
Ember.Object.create({value:'Text to display2',routename:'home'})],
actions:{
addItem(){
this.get('linksArray').pushObject(Ember.Object.create({value:'AddedDynamically',routename:'home'}));
}
}
});
in Application.hbs
<h1>Welcome to {{appName}}</h1>
<br>
{{#each linksArray as |item|}}
{{component 'link-to' item.value item.route }}
{{/each}}
<button {{action 'addItem'}}>Add Item</button>
<br>
{{outlet}}
<br>
<br>
I have a component that is wrapping content defined by another template. I want an action on the template to trigger a method in my surrounding component. Is this possible?
Here is what I have for my template. Note this is shortened for brevity.
{{#drop-down}}
<div class="menu-selector clickable" {{action "toggleDropdown"}}>
</div>
{{/drop-down}}
This is my component:
DropDownComponent = Ember.Component.extend
showDropdown: false
actions:
toggleDropdown: ->
#toggleProperty 'showDropdown'
`export default DropDownComponent`
I can verify that everything else in my component is working. If I put the action in my component that loads this template, it works fine. But that's not where I want it.
So you would like to send an action to particular components. Take a notice that
A component is a custom HTML tag whose behavior you implement using JavaScript and whose appearance you describe using Handlebars templates. They allow you to create reusable controls that can simplify your application's templates.
and
An Ember.Component is a view that is completely isolated.
You are probably using wrong tool here. You should use instead custom view.
App.DropdownView = Ember.View.extend
showDropdown: false
elemendId: 'dropdown'
actions:
toggleDropdown: ->
#toggleProperty 'showDropdown'
return;
{{#view 'dropdown'}}
<div>
<div class="menu-selector clickable" {{action "toggleDropdown"}}>
</div>
{{/view}}
Then you can send an action to view by
Ember.View.views.dropdown.send('toggleDropdown');
Demo: http://jsbin.com/zoqiluluco/1/