1

Preface:

I understand that DML is not allowed in getters/setters or constructors. The normal workaround to performing DML on page load is to use the action attribute on the page; however, that's not an option in this case.

Page:

<apex:page controller="testPageController">
    <c:testComponent/>
</apex:page>

Component:

<apex:component controller="testComponentController">
    <apex:form rendered="true">
        <apex:actionFunction action="{!init}" name="init"/>
    </apex:form>
    <script>
    init();
    </script>
</apex:component>

I have also tried a variant using $(document).ready(init()); as well as setTimeout to no avail.

When I move the <script> tag into the <apex:form> body, the error goes away; however, that's because the init method never fires.

Component controller

public class testComponentController {
    public void init() {
        update [SELECT Id FROM Contact LIMIT 1];
    }
}

I've also tried making the method return a null PageReference to no avail.

Error

When the page loads up I get the following:

DML currently not allowed

Knowing that I can't use getters, setters or constructors and apparently this doesn't work either, is there anyway to fire code when the component is loaded in a context that allows DML? Assume I don't have access to the VF page.

Update

I commented out the call to init and tried to call it from the developer console in chrome and still got the error.

4
  • Did you say (in the main page)... <apex:page controller="myController" action="{!pageInitActionHandler}"> ... and in the controller: public virtual PageReference pageInitActionHandler () { ... } ...was not workable in this case? That's what we always do. Jul 20, 2018 at 3:33
  • Yes this needs to be in the component, not at the page level.
    – gNerb
    Jul 20, 2018 at 3:46
  • What's the actual reason for needing to do this? As it stands, I feel like this is an X-Y Problem. There might be better way to do what you're trying to do.
    – sfdcfox
    Jul 20, 2018 at 3:49
  • Load page > update field on a record > send email with that record set as the target object and the updated field should be populated in the email. I need the component to work on ANY VF page and the update and email should happen without any user interaction.
    – gNerb
    Jul 20, 2018 at 4:12

1 Answer 1

2

As per the Visualforce Component Reference for <apex:component> there exists a Boolean attribute allowDML which enables executing DML within the component and the description for the same is as follows.

If this attribute is set to "true", you can include DML within the component. The default is "false". Allowing DML can cause side-effects that could be problematic for consumers using the component with partial page updates.

When allowing DML within a component, you should include rerender attributes so the consumer can appropriately refresh their page. In addition, you should detail, in the description of the component, what data is manipulated by the DML so that consumers of the component are aware of potential side-effects.

This should fix your issue.

2
  • The worst part is, I friggin knew this and just forgot :P thanks!
    – gNerb
    Jul 20, 2018 at 14:02
  • 1
    It happens to all of us. Don't worry..
    – Jigar Shah
    Jul 20, 2018 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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