how to send data from component to route ember? - javascript

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).

Related

Vue.js - switching from one component to another

I'm quite new to vue.js.
I have a page that lists details of a list of people, with an 'Edit' button against each person.
When I click the Edit button, I want to switch to another page which shows a form for editing the selected person's details.
I'm not sure what is the best way to do this. I'm using Bootstrap and Router in my solution.
Option 1: I thought it would be straightforward to route to '/person/:id' when clicking the Edit button, but not sure how to do this from the click handler method.
Option 2:
Below is the main component, where I'm trying to switch between the two components 'PersonsList' and 'EditPersonData' upon receiving an event from either. PersonsList is emitting the event successfully, but I'm not sure how to listen to it here and switch to EditPesonData component.
Home.vue
<template>
<div class="home">
<h1 class='home-text'>
{{message}}
</h1>
<component v-bind:is="component"/>
</div>
</template>
<script>
import PersonsList from '#/components/PersonsList'
import EditPersonData from '#/components/EditPersonData'
export default {
name: 'Home',
data() {
return {
message: 'Welcome to Person Details!',
component: "PersonsList"
}
},
components: {
PersonsList,
EditPersonData
}
};
</script>
Any help would be very much appreciated.
Thanks
The best way would be to send the id as a param in the route /person/:id.
To do this, you can append the id of each list item, for example:
<div v-for="(user,index) in userList" :key="index">
<a :href="'/person/' + user.id">Edit</a>
</div>
Then, you would get it in the other component as this.$route.params.id in order to get more details about the user of this id.
Make sure you define the route in the router with the id param as follows: person/:id
UPDATE :
If you want to change the route on a click function:
<b-btn #click="editPerson(user.id)">Edit</b-btn>
And in the methods, add the function as follows:
editPerson(userId){
this.$router.push({
name: 'person',
params: { id: userId }
});
}

Problem with rendering a custom component

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!

toggle element visibility in ember js based on a boolean

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.

set variable in template file from routes file

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' );

specify target action to a ember component

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/

Categories