Search code examples
javascripthtmlember.jsweb-component

While using a component multiple times how to trigger or detect all the component at once - Ember


I have created a custom component which allows user to type and also select from a dropdown. The dropdown is a dynamic div. I have managed to close all the open dropdown on clicking outside of the dropdown.But if i click a component dropdown while the other component if the dropdown is open is not getting closed. I tried to make a common model/variable and enable it only on click but it dint work. Below are my HBS and JS files

custom-dropdown.hbs

<div class="custom-dropdown">
<div class="cus-drop-text">
    {{input type=type value=inputValue   id=dropdownTF class="editableDDText" }}
</div>
<div class="cus-drop-img" {{action 'showList'}}>
    <div class="overlapDiv" >
    </div>
    <select id={{dropdownDD}}  class="pull-left editableDDSelect">
    {{#if hidealways}}
        <option value="" hidden></option>
    {{/if}}
    </select>
</div>
{{#if showList}}        
<div class="cus-drop-list {{isShowing}}" id="cus-drop-list">
    {{#each optionlist as |option|}}
    {{#if (eq selectedValue option)}}
        <span class='active cus-drop-list-item'  {{action 'onOptionChange' option}} data-value={{option}}>{{option}}</span>
        {{else}}
        <span class='cus-drop-list-item'  {{action 'onOptionChange' option}} data-value={{option}}>{{option}}</span>
    {{/if}}
    {{/each}}
</div>
{{/if}}

custom-dropdown.js

import Ember from 'ember';
export default Ember.Component.extend({
 inputName:"",
 dropdownDD: "",
 dropdownTF: "",
classNameBindings: ['isShowing'],
isShowing: 'visible',
showList:false,
hidealways:false,
isActive:false,
selectedValue: "",
inputValue:"",
didInsertElement() {
    var self=this;
    var clickFunction = function (event) {
        var target = Ember.$(event.target);
        if(target.context.className !== "overlapDiv"){
            if(!self.isDestroyed){
            self.set('showList',false);
            }
        }
    };
    window.addEventListener("click", clickFunction, false);
},

didReceiveAttrs() {
    this.set('inputName',this.get('inputID'));
    this.set('dropdownName',this.get('dropdownID'));
    this.set('dropdownTF',this.get('inputName')+"TF");
    this.set('dropdownDD',this.get('dropdownName')+"DD");       
    this.set('inputValue',this.get('value'));
},
keyPress(event){        
    this.validateInput(event);
},    

validateInput(event) {
    switch(this.get('allowedText')){
        case "numOnly":
            // Allow: backspace, delete, tab, escape, enter and numbers
            if (Ember.$.inArray(event.keyCode, [8, 9, 13, 27, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]) !== -1 ||
            // Allow: Ctrl+A, Command+A
            (event.keyCode === 65 && (event.ctrlKey === true || event.metaKey === true))) {
            // let it happen, don't do anything     
                if(Ember.$("#"+this.elementId+"TF").val().length  < this.get('allowedCharLen')+1){
                return;
                }
                else{   
                event.preventDefault();
                }
            }
            else{   
                event.preventDefault();
            }
        break;

    }
},   
actions:{
    focusOutFire:function(){
        var self =this;
        self.set('showList',false); 
    },
    onOptionChange:function(selectedValue){ 
        var self = this;
        self.set('selectedValue',selectedValue);
        self.set('showList',false); 
        self.set('inputValue',"");
        self.set('inputValue',selectedValue);
    },
    showList:function(){
        var self =this;         
        var showDropdown = true;
        // To check if the dropdown is enabled or disabled
        if(Ember.$("#"+this.get('dropdownID')+"DD").is(":disabled")){
            showDropdown = false;
        }
        else{
            showDropdown = true;
        }

        if(showDropdown){
            if(self.get('showList')){
                // Disabled Dropdown so don't show the list on click
                self.set('showList',false); 
            }
            else{
                // Dropdown is enabled                  
                self.set('showList',true);  
            }
        }
    }
}

});

enter image description here

Check the attached image. I want to close the already opened dropdown when clicking the other dropdown. Also suggest best practice to improve my ember coding in this component. Thank you for your help


Solution

  • My Problem is solved by calling the click function again using Jquery Also using mousedown is not effective in my case so im sticking to click event. This component allows user to type and also select a value from dropdown also able to select already selected value in dropdown. My final code is as below

    Custom-dropdown.hbs component-hbs

    <div class="custom-dropdown">
    <div class="cus-drop-text">
        {{input type=type value=inputValue id=dropdownTF class="editableDDText" }}
    </div>
    <div class="cus-drop-img" {{action 'showList'}}>
        <div class="overlapDiv" >
        </div>
        <select id={{dropdownDD}}  class="pull-left editableDDSelect">
        {{#if hidealways}}
            <option value="" hidden></option>
        {{/if}}
        </select>
    </div>
    {{#if displayList}}     
    <div class="cus-drop-list" id="cus-drop-list">
        {{#each optionlist as |option|}}
        {{#if (eq selectedValue option)}}
            <span class='active cus-drop-list-item'  {{action 'onOptionChange' option}} data-value={{option}}>{{option}}</span>
            {{else}}
            <span class='cus-drop-list-item'  {{action 'onOptionChange' option}} data-value={{option}}>{{option}}</span>
        {{/if}}
        {{/each}}
    </div>
    {{/if}}
    

    Custom-dropdown.js - component-js

    import Ember from 'ember';
    
    export default Ember.Component.extend({
    inputName:"",
    dropdownDD: "",
    dropdownTF: "",
    displayList:false,
    hidealways:false,
    isActive:false,
    selectedValue: "",
    inputValue:"",
    didInsertElement() {
        var self=this;
        var clickFunction = function (event) {
            var target = Ember.$(event.target);
            if(target.context.className !== "overlapDiv"){
                if(!self.isDestroyed){
                self.set('displayList',false);
                }
            }
        };
        window.addEventListener("click", clickFunction);        
    },
    didReceiveAttrs() {
        this.set('inputName',this.get('inputID'));
        this.set('dropdownName',this.get('dropdownID'));
        this.set('dropdownTF',this.get('inputName')+"TF");
        this.set('dropdownDD',this.get('dropdownName')+"DD");       
        this.set('inputValue',this.get('value'));
    },
    didDestroyElement(){
        window.removeEventListener( 'click',  clickFunction);
    },
    
    keyPress(event){        
        this.validateInput(event);
    },    
    
    validateInput(event) {
        switch(this.get('allowedText')){
            case "numOnly":
                // Allow: backspace, delete, tab, escape, enter and numbers
                if (Ember.$.inArray(event.charCode, [8, 9, 13, 27, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57]) !== -1 ||
                // Allow: Ctrl+A, Command+A
                (event.charCode === 65 && (event.ctrlKey === true || event.metaKey === true))) {
                // let it happen, don't do anything     
                    if(Ember.$("#"+this.elementId+"TF").val().length  < this.get('allowedCharLen')+1){
                    return;
                    }
                    else{   
                    event.preventDefault();
                    }
                }
                else{   
                    event.preventDefault();
                }
            break;
    
        }
    },   
    actions:{
        onOptionChange:function(selectedValue){ 
            var self = this;
            self.set('selectedValue',selectedValue);
            self.set('displayList',false);  
            self.set('inputValue',"");
            self.set('inputValue',selectedValue);
        },
        showList:function(){
            var self =this;         
            var showDropdown = true;
            // To check if the dropdown is enabled or disabled
            if(Ember.$("#"+this.get('dropdownID')+"DD").is(":disabled")){
                showDropdown = false;
            }
            else{
                showDropdown = true;
            }
            // Dropdown is enabled so show the list 
            if(showDropdown){
                if(self.get('displayList')){
                    // Hide the Dropdown list 
                    self.set('displayList',false);  
                }
                else{       
                    // Hide all the open dropdown
                    Ember.$("body").click();
                    // Show the Dropdown list               
                    self.set('displayList',true);   
                }
            }
        }
      }
    });
    

    Component usage in HBS

    {{custom-dropdown type="text" value=model.priceLessThan dropdownID="openingPrice" inputID="openingPrice" id="openingPrice" optionlist=content.opening allowedCharLen=5 allowedText="numOnly" actionName="opnPriceLessChange"}}