0

I am new on Salesforce/Lightning and I'm trying to implement this OrgChart library in a lightning component. The nodes (html) are created dynamically from the javascript library, the methods are called using classes + jQuery, for example :

Class : 'add_node'.
Method : $("#add_node)...

To be able to change that, I copied the whole library inside the lightning component 'helper' and here is my current "add_node" function.

$("#add_node").click(function(e) {
    console.log('you clicked!');
});

The thing here is that the $("#classExample").click(function(e) { methods are not working. I tried to put like a console.log on it and it simply doesn't run. Also, I tried to change the method to .on("click",(function(e)){} but it didn't work as well.

Here is my .cmp :

<aura:component controller="hierarchyCompController" >
<ltng:require styles="/resource/OrgChartJit2/css/style.css"
              scripts="/resource/cs_community/lib/jquery-1.11.3.min.js,
                       /resource/cs_community/theme/js/bootstrap.min.js,
                       /resource/cs_community/lib/bootstrap-datepicker.js,
                       /resource/cs_community/theme/js/moment.min.js,         
                       /resource/cs_community/theme/js/jquery-ui.min.js,
                       /resource/cs_community/lib/accounting.min.js,
                       /resource/cs_community/lib/jquery.base64.js,
                       /resource/OrgChartJit2/libs/jit/jit2.js,
                       /resource/OrgChartJit2/js/tree.organization.js"

              afterScriptsLoaded="{!c.doInit}" />
    <body>
        <div id="infovis"></div>
    </body>
</aura:component>

Here is my js Controller:

({
    doInit : function(component, event, helper) {
         helper.createOrg(component,event,helper);
    }
})

Here is my helper:

({
    createOrg : function(component, event, helper) {
        var json = {"children":[{"name":"General Committee","id":80,"children":[{"name":"Executive Committee","id":81,"children":[{"name":"Executive Director","id":82,"children":[{"name":"Operation Assistant","id":83,"children":[{"name":"PC(EIGP)","id":85,"children":[{"name":"Officer","id":91,"children":[],"data":{"code":"3","type":"Type 1","description":"The description of Officer","type_id":1}}],"data":{"code":"3","type":"Type 2","description":"The description of PC(EIGP)","type_id":2}},{"name":"PC(SDP)","id":86,"children":[{"name":"Supervisor","id":92,"children":[],"data":{"code":"3","type":"Type 1","description":"The description of Supervisor","type_id":1}}],"data":{"code":"3","type":"Type 2","description":"The description of PC(SDP)","type_id":2}},{"name":"PC(HRRDP)","id":87,"children":[{"name":"Data Collector","id":93,"children":[],"data":{"code":"3","type":"Type 1","description":"The description of Data Collector","type_id":1}}],"data":{"code":"3","type":"Type 2","description":"The description of PC(HRRDP)","type_id":2}}],"data":{"code":"3","type":"Type 2","description":"The description of the Operation Assistant","type_id":2}},{"name":"Finance Assistant","id":84,"children":[{"name":"Chief Auditor","id":88,"children":[{"name":"Auditor","id":95,"children":[],"data":{"code":"3","type":"Type 1","description":"The description of Auditor","type_id":1}}],"data":{"code":"3","type":"Type 1","description":"The description of Chief Auditor","type_id":1}},{"name":"Chief Accountant","id":89,"children":[{"name":"Cashier","id":96,"children":[],"data":{"code":"3","type":"Type 1","description":"The description of Cashier","type_id":1}}],"data":{"code":"3","type":"Type 2","description":"The description of Chief Auditor","type_id":2}},{"name":"Chief Administrative Officer","id":90,"children":[{"name":"Store Keeper","id":97,"children":[],"data":{"code":"3","type":"Type 1","description":"The description of Store Keeper","type_id":1}}],"data":{"code":"3","type":"Type 1","description":"The description of Administrative Officer","type_id":1}}],"data":{"code":"3","type":"Type 2","description":"The description of the finance assistant","type_id":2}}],"data":{"code":"3","type":"Type 2","description":"The description of the executive director","type_id":2}}],"data":{"code":"2","type":"Type 2","description":"The description of the executive committee","type_id":2}}],"data":{"code":"1","type":"Type 1","description":"The description of the general committee","type_id":1}}],"name":"Technology Inc.","id":0}; 
            console.log('helper');
            $("#add_node").click(function(e) {
                 console.log('you clicked!');
            });
            var height = ($('#infovis').height() / 2) - 60;
            //init Spacetree
            //Create a new ST instance
            st = new $jit.ST({
                orientation: "top",
                //id of viz container element
                injectInto: 'infovis',
                //set duration for the animation
                duration: 100,
                //set animation transition type
                transition: $jit.Trans.Quart.easeInOut,
                //set distance between node and its children
                levelDistance: 60,
                //enable panning
                Navigation: {
                    enable:true,
                    panning:true,
                    zooming: 5
                },
                //set node and edge styles
                //set overridable=true for styling individual
                //nodes or edges
                Node: {
                    height: 80,
                    width: 200,
                    type: 'rectangle',
                    color: '#4b6a86',
                    overridable: true
                },

                Edge: {
                    type: 'bezier',
                    overridable: true
                },

                //Needed for not hiding
                constrained: false,
                levelsToShow: 3,

                //This method is called on DOM label creation.
                //Use this method to add event handlers and styles to
                //your node.
                onCreateLabel: function(label, node){

                    label.id = node.id;
                    var actions;
                    //var add_node_link ='<table><tr><th></th></tr><tr><td onclick="{!c.openModal}" >ola</td></tr></table>';
                    var add_node_link = '<a class="add_node"></a>';
                    var delete_node_link = '<a class="delete_node"></a>';
                    var edit_node_link = '<a class="edit_node"></a>';
                    var action_class = '';
                    if (node.id == 0) {
                        add_node_link = '<a class="add_node alone"></a>';
                        delete_node_link = '';
                        edit_node_link = '';
                        action_class = 'options_works';
                    }
                    actions = '<p><div class="options ' + action_class + '" style="display: none;">' + add_node_link + edit_node_link + delete_node_link + '</div></p>';
                    if(node.name) {
                        label.innerHTML = '<div class="node_container"><label class="node_name">' + node.name.substr(0, 40)+'<br/><br/><div class="node_container"><label class="node_name">' + node.data.description +'</label></div></label>'+actions+'</div>';
                    }
                    label.onclick = function(){
                        make_movement(node);
                    };

                    //event to show/hide the options of node
                    $(label).hover(function(){
                        $(this).find('div.options').show();
                    }, function(){
                        $(this).find('div.options').hide();
                    });

                    //event to stop propagation of the add, edit and delete nodes
                    $(label).find('.options').children('.edit_node, .add_node, .delete_node, .node_info').click(function (e) {

                        if($(this).hasClass('edit_node')){
                            show_edit_form($(this));
                        } else if($(this).hasClass('add_node')){
                            show_add_form($(this));
                        } else if($(this).hasClass('delete_node')){
                            show_delete_form($(this));
                        } else if($(this).hasClass('node_info')){
                            show_node_info($(this));
                        }
                        e.preventDefault();
                        e.stopPropagation();
                    });

                    //set label styles
                    var style = label.style;
                    style.width = 200 + 'px';
                    style.minHeight = 80 + 'px';
                    style.cursor = 'pointer';
                    style.color = '#333';
                    style.fontSize = '0.8em';
                    style.textAlign= 'center';
                    style.paddingTop = '3px';
                },

                //This method is called right before plotting
                //a node. It's useful for changing an individual node
                //style properties before plotting it.
                //The data properties prefixed with a dollar
                //sign will override the global node style properties.
                onBeforePlotNode: function(node){
                    //add some color to the nodes in the path between the
                    //root node and the selected node.
                    var nodes_color = ['#2199CC', '#27B5F1', '#60CFFE'];
                    if (node.selected) {
                        node.data.$color = "#136283";
                    }
                    else {
                        delete node.data.$color;
                        node.data.$color = nodes_color[node._depth>2 ? 2: node._depth];

                        //if the node belongs to the last plotted level
                        if(!node.anySubnode("exist")) {
                            //count children number
                            var count = 0;
                            node.eachSubnode(function(n) { count++; });
                            //assign a node color based on
                            //how many children it has
                            if(count > 0)
                                node.data.$color = '#E9BC42';
                        }

                    }
                    setLabelScaling();

                },

                //This method is called right before plotting
                //an edge. It's useful for changing an individual edge
                //style properties before plotting it.
                //Edge data proprties prefixed with a dollar sign will
                //override the Edge global style properties.
                onBeforePlotLine: function(adj){
                    if (adj.nodeFrom.selected && adj.nodeTo.selected) {
                        adj.data.$color = "#BFBBC0";
                        adj.data.$lineWidth = 3;
                    }
                    else {
                        delete adj.data.$color;
                        delete adj.data.$lineWidth;
                    }
                }
            });
            //load json data
            st.loadJSON(json);
            //compute node positions and layout
            st.compute();
            //optional: make a translation of the tree
            //st.geom.translate(new $jit.Complex(-200, 0), "current");
            //emulate a click on the root node.
            st.onClick(st.root, {
                Move: {
                    offsetX: 0,
                    offsetY: height,
                    enable: true
                }
            });

            var top = $jit.id('r-top'),
                left = $jit.id('r-left'),
                bottom = $jit.id('r-bottom'),
                right = $jit.id('r-right'),
                normal = $jit.id('s-normal');


            function changeHandler() {
                if(this.checked) {
                    top.disabled = bottom.disabled = right.disabled = left.disabled = true;
                    st.switchPosition(this.value, "animate", {
                        onComplete: function(){
                            top.disabled = bottom.disabled = right.disabled = left.disabled = false;
                        }
                    });
                }
            }

    }
})

The comments inside the helper are from the original library.

Am I doing something wrong or is there other way to handle this click events inside a lightning component?

P.S : I am not able to add an onClick method inside the node, since there is a 'Content Security Policy', that blocks the whole thing from the browser.

Thanks in advance.

6
  • 1. can you add your component code? 2. have you added jquery in your lightning component.
    – Himanshu
    Commented Jun 19, 2017 at 4:51
  • The component it self just use a tag to display the nodes, like this : <body> <div id="infovis"></div> </body> jQuery is added and it is working, since the graphs are being displayed, just the methods are not working.
    – msonza
    Commented Jun 19, 2017 at 4:54
  • I am asking because you might be missing some basics. are you using afterScriptloaded? and component means your controller, component, helper
    – Himanshu
    Commented Jun 19, 2017 at 4:57
  • Please take a look now, let me now if you need more info.
    – msonza
    Commented Jun 19, 2017 at 5:04
  • You should try the latest stable version of jQuery. Commented Jun 19, 2017 at 5:07

3 Answers 3

1

Just for the record, this issue was happening due to JQuery version. I was using 1.11.3 and according to this post, it has to be versions like 2.2.2 or 2.2.4. After I uploaded a new version, this issue were solved.

0

As per the code, there are two points I have noticed -

  • add_node on which you are trying to bind a click event is a class, and you are using # to bind the click event. # is an ID selector, in this case you need to use . (dot) selector
  • In the component code there is only one html element I can see that is div having id infovis there is no element with class add_node when component is loaded

My Findings -

  • You are binding the click event on component load, exactly after the scripts is getting loaded.

  • The html element having class add_node is generated inside one of the JS code.

  • So when the code $(".add_node").click(function(e) { console.log('you clicked!'); }); is triggered there is no such element with add_node class

  • So in this case you need to bind events on the element which will be generated in future rather then binding events on the component/script load.

For this you can use jQuery delegate method For ex -

     $(document).delegate(".add_node", "click", function() {//Your code goes here});

So replace your jQuery click method with delegate method and use . (dot) selector instead of # (ID) selector.

Hope this helped you..

0

You can try this to verify it's being bound

$("#infovis").on("click", "#add_node", function () { 
    console.log('test'); 
});

If that doesn't work try using body.

$("body").on("click", "#add_node", function () { 
    console.log('test'); 
});

Or use the class name instead of the Id element.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .