+ Start a Discussion
JackMckracken83JackMckracken83 

JQuery dialog form - returning new record ID

I'm currently using jsTree in a Visualforce page as an interface to add/edit records. The user can right click on an element in the tree, select New from the context menu, and a form for adding a new record is loaded into a JQuery dialog box. Once they submit the form, I need to pass the ID of the new record to a function that will add a new node to the jsTree with an id = the new record ID. So far I'm having zero luck. I'm overriding the standard controller's "save" action in order to set an id variable so that it can be accessed via JQuery, but its never getting set.

 

Controller Extension:

public with sharing class extTrack {
    private Apexpages.StandardController controller;
    private final Track__c track;
    
    public String trackId { get; set; }
    
    public extTrack(ApexPages.StandardController stdController){
        this.controller = stdController;
        this.track = (Track__c)stdController.getRecord();
    }
    
    public PageReference saveTrack() {
        String trackId = ApexPages.currentPage().getParameters().get('id');
        
        if(trackId == null) {
            insert track;
            trackId = track.id;
        } else {
            this.controller.save();
        }
        
        return null;
    }
}

 

VisualForce page:

<apex:page standardController="Track__c" extensions="extTrack" showHeader="false" sidebar="false">
    <apex:includescript value="{!URLFOR($Resource.CKEditor, 'ckeditor/ckeditor.js')}" />
    <script>
        function closeTrack() {
            alert("{!trackId}"); //this is always blank
            if($.trim('{!trackName}') != '') var newNode = addNode($('tracks'),'{!trackName}','{!trackId}',false);
            $("#objProps").dialog("close");
        }
    </script>
    <apex:form >
        <apex:pageBlock >
            <apex:pageMessages />
            <div>
                <div class="propsLbl">Name:</div>
                <apex:inputField value="{!Track__c.Name}" />
            </div>
            <div>
                <div class="propsLbl">Description:</div>
                <apex:inputtextarea id="trackDesc" value="{!Track__c.Description__c}" styleClass="ckeditor" richtext="false"/>
                <script>
                    CKEDITOR.replace( '{!$Component.trackDesc}',
                        {
                            filebrowserBrowseUrl : '{!$Page.SiteFileBrowser}',
                            filebrowserImageBrowseUrl : '{!$Page.SiteFileBrowser}'
                        });
                        
                    function beforeTextSave() {
                        var objEditor = CKEDITOR.instances['{!$Component.trackDesc}'];
                        document.getElementById('{!$component.trackDesc}').value = objEditor.getData();
                    }
                </script>
            </div>
            <div>
                <div class="propsLbl coll">Active:</div>
                <apex:inputField value="{!Track__c.Active__c}" />
            </div>
            <div class="propsBtns">
                <apex:commandButton value="Cancel" onClick="CKEDITOR.instances['{!$Component.trackDesc}'].destroy();$("#objProps").dialog("close");" reRender="none" />
                <apex:commandButton value="Save Track" onClick="beforeTextSave();" action="{!saveTrack}" reRender="none" status="saveStatus" />
                <apex:actionStatus startText="(Saving...)" onStop="closeTrack()" id="saveStatus"/>
            </div>
        </apex:pageBlock>
    </apex:form>
</apex:page>

sfdcfoxsfdcfox

This code fails because {!trackId} won't be re-evaluated after the save function occurs. You have a few ways which you can fix this, but I think the most forward method would be to:

 

<!-- in visualforce page -->
<script>
function closeTrack() {
  var trackId = $('{!$Component.form.trackId}).value
  // ...
}
</script>
<apex:form id="form">
<apex:inputHidden id="trackId" value="{!trackId}"/>
<!-- ... -->
<apex:commandButton action="{!closeTrack}" reRender="form" onComplete="closeTrack()" />

Should be fairly obvious how it all glues together from here. The only final lacking part is to make sure you catch the controller.save()'s redirect if that's how you're going to save, because that will return the user from your VF page to the page they were on (their retURL value).

JackMckracken83JackMckracken83

i don't want to rerender anything (i've got rerender set to "none"). i'm trying to accomplish this all without a refresh - when the user clicks Save, the dialog should close and a new node with the object ID as its ID should be added to the jstree.

sfdcfoxsfdcfox

The point of a reRender is to avoid a refresh. You could choose to move the script tag inside your form tag, and reRender just the script tag. The point is you must pass the data back to the browser somehow. Realistically, you have four non-"refreshing" choices: reRender (as in the prior example), an @ActionFunction (see the docs), as a WebService function (API call), or by using sforce.apex.execute() (In the AJAX Toolkit). reRender is the easiest, as you've already got about 90% of the code written. The others are also easy to implement, and the choice of how you do it doesn't matter, but you need to initiate some sort of AJAX action in the browser to get the ID back.