18

I have this Visualforce code snippet in a page:

<apex:outputLink value="javascript:if (window.confirm('Are you sure?')) DeleteQuoteLineItem('{!LineItem.QuoteLineItem.Id}');">
    Del
</apex:outputLink>

<apex:actionFunction action="{!DeleteQuoteLineItem}" name="DeleteQuoteLineItem" reRender="content">
    <apex:param value="test"/>
</apex:actionFunction>

The two methods I'm using for testing are:

public void DeleteQuoteLineItem(String RecordID)
{
    System.debug('method with a paramater');
    System.debug(RecordID);
}

public void DeleteQuoteLineItem()
{
    System.debug('method without a parameter');
}

Everytime I click on the link to execute the apex:actionFunction, it's calling the DeleteQuoteLineItem() method without any parameter. I looked online and it seems like I need to create a class attribute and use assignTo= in my apex:param to populate it accordingly.

Is it possible to prevent this behavior and use standard method parameters, so I don't have to create class attributes? I want to work on a clean and optimized codebase, preventing unnecessary variable scope (so no class attribute when it's not required) and improve code re-usability by staying context agnostic.

Thanks

  • Just curious, but what's the use case. Why are you opposed to using a class property to assign the param to? Or are you just curious if it's possible? – Chris Duncombe Jan 14 '14 at 16:27
  • 1
    It's just to make sure that data that do not require such a scope doesn't end up in a class attribute. I don't need the value sent by my action:actionFunction to be available in all the class, it's pointless :)! – jpmonette Jan 14 '14 at 16:32
  • ok, I was just curious. Added an answer that hopefully helps. – Chris Duncombe Jan 14 '14 at 16:36
18

You can access the param that was passed directly inside you controller using the ApexPages class or the system class.

VF

<apex:outputLink value="javascript:if (window.confirm('Are you sure?')) DeleteQuoteLineItem('TEST VALUE');">
    Del
</apex:outputLink>

    <apex:actionFunction action="{!DeleteQuoteLineItem}" name="DeleteQuoteLineItem" reRender="content">
        <apex:param name="myParam" value=""/>
    </apex:actionFunction>

Apex

public void DeleteQuoteLineItem(){

    //either of the next 2 lines will work, 
    string passedParam1 = Apexpages.currentPage().getParameters().get('myParam');
    string passedParam2 = system.CurrentPageReference().getParameters().get('myParam');
    system.debug(passedParam1);
    system.debug(passedParam2);
}

Im just curious as to why you are opposed to using class properties to assign the params to. Both ways will work, just curious if you have a unique use case or just curious of other ways of accomplishing it. Hope this helps

  • 1
    Because the argument doesn't require such a scope within the class. Just like any other language, you shouldn't unnecessarily increase the scope of a variable when it doesn't need such a scope. Any other method inside this class could mess with the value. That's what method arguments are for, to prevent that. – jpmonette Jan 14 '14 at 16:47
  • You don't need to assign it to a variable, you can pass it directly to a method or however you want to use it. If you don't want to assign it to a variable, then don't assign it to a variable. This allows you to pass the value to a controller without using a class attribute, which is what I thought you asked in the question. – Chris Duncombe Jan 14 '14 at 16:52
  • 1
    Using ApexPages brings another issue: non-agnostic context. If I want to call this method from a trigger, I'll hit an error. Just trying to follow good practices and improve code reusability. – jpmonette Jan 14 '14 at 17:00
  • 1
    I get that, but I would update your question to include these parameters for people to consider. Your question is much more general, and now you're bringing in new requirements in comments. I would update the question to explain exactly what you are looking for to avoid lengthy comments like this. – Chris Duncombe Jan 14 '14 at 17:13
9

If you want to pass data which does not require scope within the whole controller class, but rather requires to be visible only in the scope of called controller method, maybe you could consider using apex js remoting? E.g. your example with the js remoting approach might look like:

VF page:

<apex:outputLink value="javascript:if (window.confirm('Are you sure?')) DeleteQuoteLineItem('TEST VALUE');">
    Del
</apex:outputLink>

<script type="text/javascript">
    function DeleteQuoteLineItem(param) {
        Visualforce.remoting.Manager.invokeAction(
            '{!$RemoteAction.MyController.DeleteQuoteLineItem}', 
            param, 
            function(result, event){
                if (event.status) {
                    DeleteQuoteLineItemCallback();
                } else if (event.type === 'exception') {
                    // handle exception
                } else {
                    // handle error
                }
            }
        );
    }
</script>
<apex:actionFunction name="DeleteQuoteLineItemCallback" reRender="content"></apex:actionFunction>


...while your controller should contain this method:

@RemoteAction
public static void DeleteQuoteLineItem(string param) {
    system.debug(param);
}


The solution above does however have one drawback - in order for the content outputPanel (or whichever component it is) to be rerendered, success callback for the initial remote method call will invoke yet another actionFunction, whose sole purpose is to rerender the content panel.

Maybe could be done a bit tidier, but nothing comes to mind at the moment :)

  • Totally Awesome if you don't need a View State (+ way faster) – Scott Pelak Feb 26 '16 at 0:44

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.