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.

  • 1. can you add your component code? 2. have you added jquery in your lightning component. – Himanshu Jun 19 '17 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 Jun 19 '17 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 Jun 19 '17 at 4:57
  • Please take a look now, let me now if you need more info. – msonza Jun 19 '17 at 5:04
  • You should try the latest stable version of jQuery. – itzmukeshy7 Jun 19 '17 at 5:07
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.