2

I'm trying to write a Lightning component renderer that has an external script dependency, specifically CKEditor. I know there's already a Lightning rich text component that uses CKEditor but it doesn't do everything I'd like it to.

I've got my own CKEditor static resource loaded by ltng:require, the problem is that neither render, rerender or afterRender have access to the script on first load using ltng:require. Is there a way to guarantee that the render is run after scripts are loaded?

I've tried the doneRendering event but it is still undefined and my understanding is that dom manipulation shouldn't be done outside of the renderer

({
render: function(component, helper) {
    var ren = this.superRender();

    console.debug('Render CKEditor: '+typeof CKEDITOR);
    console.debug('Render $: '+typeof $);


    return ren
},

rerender: function(component, helper){

    this.superReRender();

    console.debug('ReRender CKEditor: '+typeof CKEDITOR);
    console.debug('ReRender $: '+typeof $);

},

afterRender: function(component, helper) {

    console.debug('afterRender CKEditor: '+typeof CKEDITOR);
    console.debug('afterRender $: '+typeof $);

}

})

<aura:component>


<ltng:require scripts="/resource/cmsltng__jqueryui/js/rendering/jquery.min.js,
     /resource/cmsltng__jqueryui/js/rendering/jquery-ui.min.js,
     /resource/cmsltng__ckedit/ckeditor/ckeditor.js" />


<aura:handler event="aura:doneRendering" action="{!c.initCKEditor}" />  

<textarea aura:id="richText"></textarea>

There's a similar question but the answers are stale and pre ltng:require

How to use jQuery (or any JS lib) in initial post rendering of Lightning Components

2

There is a "afterScriptsLoaded" event that gets fired when all of your ltng:require stuff finishes loading. I suppose you can have some renderer code that runs afterSciptsLoaded. For example

<ltng:require scripts="/resource/cmsltng__jqueryui/js/rendering/jquery.min.js,
 /resource/cmsltng__jqueryui/js/rendering/jquery-ui.min.js,
 /resource/cmsltng__ckedit/ckeditor/ckeditor.js"
 afterScriptsLoaded="{!c.afterLoad}"/>

And then a controller like so:

render: function(component, event, helper) {
    var ren = this.superRender();
    //etc...
    return ren
},
afterLoad: function(component, event, helper) {
    this.render(component, event, helper);
},
  • 1
    Thanks! I just tried that and it works. My only concern now is that it's bad form to modify the dom there. Mind you it seems like using any external scripts while possible is bad form. – Scott Morrison Jul 14 '15 at 16:55
  • 1
    Have an attribute on your component such as scriptsLoaded that gets set to true in the afterLoad event, and then force a re-render. Have your renderer/rerenderer check that attribute and if it is true, execute the editor code? – Christian Carter Jul 17 '15 at 3:38
  • As an aside CKeditor has some security issues with locker service that I don't think are being resolved so CKEditor in lightning is a bad idea – Scott Morrison Feb 15 '17 at 21:25
0

this.superRender() in controller won't work. Try this instead.

Component:

<aura:component>
        <ltng:require scripts="/resource/CKEditor" afterScriptsLoaded="{!c.afterLoad}" />  
        <aura:attribute name="isCKEditorLoaded" type="Boolean" default="false"/>
</aura:component>

Controller:

({
    afterLoad: function(component, event, helper) {
        component.set("v.isCKEditorLoaded", true);
    }
})

Helper:

({
    modifyDom: function(component) {
        if(component.get("v.isCKEditorLoaded")) {
            //Do the required DOM modification
        }

    }
})

Renderer:

({
    afterRender: function(component, helper) {
        this.superAfterRender();
        helper.modifyDom(component);
    }
})

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.