2

I'm actually referencing to a js method defined in my external js file, in my lightning component. But it refuses to recognise my method. Here is my code :

visualforce page :

<apex:page showheader="false" standardstylesheets="false" controller="VFC01_DisplaySimpleLayoutDetails">

<apex:includelightning />
<div id="xi-div-container" />

<script>
    var wsname = "{!$CurrentPage.parameters.wsname}"; // the webservice to be called
    var template = JSON.parse('{!strResult}');
    var abbreviations = JSON.parse('{!strAbbreviations}');        
    var param1 = "{!$CurrentPage.parameters.param1}"; // the parameter to pass to the ws

    $Lightning.use("c:LA01_GeneratePlainLayout",
                    function() {
                      $Lightning.createComponent("c:LC01_GeneratePlainLayout",
                      {"WSName" : wsname,
                        "template" : template,
                        "abbreviations" : abbreviations,
                        "param1" : param1
                      },
                      "xi-div-container",
                      function(cmp) {
                        // do nothing for now, just create the component
                      });
                    });


  </script>
 </apex:page>

My lightning app :

 <aura:application access="GLOBAL" extends="ltng:outApp" >
     <ltng:require styles="{!$Resource.SLDS202_HV1 + '/assets/styles/salesforce-lightning-design-system.min.css'}"
                scripts="{!$Resource.GI_CustomHelpers + '/helper01.js'}" />
     <aura:dependency resource="c:LC01_GeneratePlainLayout"/>
 </aura:application>

My lightning cmp :

  <aura:component controller="LC01_WSCaller">  
    ......
    ......
    .......
   <div class="slds-button__icon xc-icon-bk-right" onclick="toggleSection(this,'x-card-1')"></div>

the toggleSection method is defined in my external js file. And for some reason I need to use the method defined in my js file, because div is generated dynamically, so i cannot , for now, use the controller action or helper methods. when i click on the button, I'm obtaining the following error message :

  Uncaught ReferenceError: toggleSection is not defined throws at https://xxxxprooffice--agsdev--c.cs5.visual.force.com/apex/VFP01_Display?tpname=Customer_Detail_Page_Template&wsname=RetrieveCustomerDetails&param1=0008227:1:1

but if I place the same method in my visualforce page in the script section, it works like a charm :

 .....................

 <script>
    var wsname = "{!$CurrentPage.parameters.wsname}"; // the webservice to be called
    var template = JSON.parse('{!strResult}');
    var abbreviations = JSON.parse('{!strAbbreviations}');        
    var param1 = "{!$CurrentPage.parameters.param1}"; // the parameter to pass to the ws

    $Lightning.use("c:LA01_GeneratePlainLayout",
                    function() {
                      $Lightning.createComponent("c:LC01_GeneratePlainLayout",
                      {"WSName" : wsname,
                        "template" : template,
                        "abbreviations" : abbreviations,
                        "param1" : param1
                      },
                      "xi-div-container",
                      function(cmp) {
                        // do nothing for now, just create the component
                      });
                    });

      function toggleSection(me, divid){
        ...........
        .............
        .............   
       }  
</script>

I do not want to place my js methods like this in my visualforce page. I want to be able to load a js file with my methods defined inside. How can i make it work??? Anyone with this problem ??

Update:

On chrome (developer mode), when I click on sources, in my helper01.js file, i have the following codes , with strict added :

function $globalEvalIIFE$(){with(arguments[1]||{}){with(arguments[0]||{}){return (function(window){
    "use strict";
     function hasClass(element, cls) {
       ...............
    }
    function toggleBetweenClasses(me,cls1,cls2){
      .........
    }
    function toggleSection(me, divid){
      ...............           
    }

}).call(arguments[0], arguments[0])}}}

If I add a method for testing purpose like this :

  window.toggleVisibility = function(eid){
       alert("element id is :" + eid);
    };

When i click on my button i got the following error :

Uncaught ReferenceError: toggleVisibility is not defined throws at https://......................

What am I doing wrong ?

6
  • Have you tried calling the toggleSection method from an controller/helper method?: <div onclick="{!c.callToggleSection}"/> and in your controller.js : callToggleSection: function(cmp,evt,helper){ toggleSection(evt.currentTarget, 'x-card-1'); }
    – Praveen
    Commented Aug 12, 2016 at 8:06
  • The problem is that this div is dynamically created , so c.callToggleSection is not recognise
    – vanessen
    Commented Aug 12, 2016 at 10:03
  • It will recognize. What behavior you see, when clicking on the div?
    – Praveen
    Commented Aug 12, 2016 at 10:09
  • 2
    FYI, in your visualforce page you have some reflected cross site scripting vulnerabilities. You need to JSENCODE() the merge fields in a script context, otherwise an attacker can supply their own HTML markup in URL parameters and it will be injected into your page. Commented Aug 13, 2016 at 7:12
  • @vanessen See my answer here this will help you out.
    – Praveen
    Commented Aug 17, 2016 at 9:21

1 Answer 1

3

Interesting - there are a few things going on here I think but let's first focus on the use of onclick= bound to a non aura client side controller - that should plain not work, ever. In aura markup what looks like a simple div is actually syntactic shorthand for something more like:

<aura:html tag="div" HTMLAttributes="{!bagOfAttributes}">

and in LC/Aura all event handlers must be bound to {!c.someHandler} expressions and not plain old JavaScript. If direct binding to a global plain old JavaScript function works I believe it's 100% unintentional and likely to be "fixed"/removed.

Second, this looks like LockerService's expected behavior inherited because all component JavaScript and any external JavaScript you require/import now runs with JavaScript strict mode enabled which cleans up many long standing global scope issues. In helper01.js are you publishing toggleSection() as a global variable? In other words simply declaring a function no longer makes it global - same is true for any variable/object in strict mode. You need to explicitly indicate that you want it added to global scope like so:

window.toggleSection = toggleSection;

You can of course directly assign window.toggleSection = function() { ... };

This is a strict mode standard and is not specific to LS.

Lastly, ltng:require is itself a Lightning component and is designed to be used inside of the component lifecycle - it's dynamically including your CSS and scripts much like RequireJS and other dynamic loaders do with a twist: it's integrated into the init/render flow. It removes most of the issues around dynamic loading (inherently asynchronous) and LC's component lifecycle but to get the benefits you'll need to work inside of the life cycle's constraints.

1
  • @praveen : when i click on the div it says : Uncaught ReferenceError: c.toggleVisibility is not defined throws .....
    – vanessen
    Commented Aug 16, 2016 at 14:06

You must log in to answer this question.

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