Julien Vincent
Julien Vincent

Reputation: 1238

How to listen for clicks within an action - emberjs best practices

I have started learning emberjs quite recently and am struggling to get a understanding on how different components interact with each other, as well as the best practices for doing things.

What I am looking to do is use the class binding ember provides to reproduce the following crude jquery functionality:

import Ember from "ember";

export default Ember.Component.extend({
    actions: {
        showMenu: function() {
            $('.menu-bar').removeClass('hideMenu');
            $('.menu-bar').addClass('showMenu');

        $('.page').click(function() {
            $('.menu-bar').removeClass('showMenu');
            $('.menu-bar').addClass('hideMenu');
        });
    }
}
});

What I have done so far is this:

import Ember from "ember";

export default Ember.Component.extend({
    showMenu: false,
    actions: {
        showMenu: function() {
            this.set('showMenu', true);
        }
    }
});

My menu-bar component looks like this:

<div {{bind-attr class=":menu-bar showMenu:menuSlideDown:menuSlideUp"}} {{action 'showMenu'}}>
</div>

and finally my template being loaded into {{outlet}} looks like this:

<div {{bind-attr class=":page :home :current"}}>
    {{menu-bar}}
    <div class="splash center button-perspective">
    </div>
</div>

I would like to know the "best practice" for the required functionality. Also please note I am using ember-cli.

I could add a {{action}} listener on the element 'page' but I have multiple templates with the 'page' class and so would have to add this listener to all the pages - also this means it will trigger every time page is clicked which feels dirty to me. I would like to handle all the actions belonging to my menu-bar.js component inside the menu-bar's controller. Is that sound logic and if yes\no, what is the best way of doing this?

If additional information is required I am happy to provide - also any and all criticism is welcomed.

Upvotes: 2

Views: 247

Answers (1)

Vaibhav
Vaibhav

Reputation: 1477

This can be an example to achieve the functionality

//In any view template, consider custom-form as a component
{{custom-form dataSet=model.data action='submitForm'}}

//In custom-form.hbs
<div class="container">
    <div class="header">
    <span>Form</span>   
    {{#if isExpanded}}
        <span class="arrow"{{action "toggleExpanded"}}><i class="glyphicon glyphicon-triangle-bottom"></i></span>
    {{else}}
        <span class="arrow" {{action "toggleExpanded"}}><i class="glyphicon glyphicon-triangle-top"></i></span>
    {{/if}} 
    </div>  
    {{#if isExpanded}}
        {{#each qObj in dataSet}}
        <div class="form-group">
            <label>{{qObj.question}}</label>
            {{input value=qObj}}
        </div>
        {{/each}}
    {{/if}}
    <button {{action 'submitForm'}}>Submit</button>
</div>

//In custom-form.js
import Ember from 'ember';
import layout from '../templates/components/custom-form';

export default Ember.Component.extend({
  layout: layout,
  isExpanded:true,
  actions:{
    submitForm:function(){
        this.sendAction(); //This will send action to outside application
    },
    toggleExpanded:function(){
        this.toggleProperty('isExpanded');
    }
  }
});


//In any controller which is the context of component
import Ember from 'ember';

export default Ember.Controller.extend({
    actions:{
        submitForm:function(){
            alert('From Controller');
            console.log(JSON.stringify(this.get('model.data')));
        }
    }
});

Now here action='submitForm' is defined, this method name can be any name which you would be implementing in your controller, if you want to handle some specific functionality on the basis of components action. And normal actions of components would be handled inside the component only, like 'toggleExpanded' and 'submitForm' . Now to send an action from component to application, use sendAction method.

Now files related to components would be only in templates/componets/.hbs and components/.js

Upvotes: 2

Related Questions