2

EDITED, clarity, removing secondary questions...

I am trying to create a note record onto a contact, from a modal (a stacked modal). I have an issues with passing the ID to APEX...

My issue is that when I create the note record, the contact ID is not being passed through to the second modal through the 'new' button. I have tried a hidden value, but with no success. In the markup, i have hard coded the id for testing purposes.

Thanks in advance, Mike

(APOLOGIES for code length, however have made it so it can be copied into any environment)

VF:

<apex:page showHeader="false" standardStylesheets="false" controller="modalCreateRecord">

<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"/>
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/jasny-bootstrap/3.1.3/css/jasny-bootstrap.min.css"/>

<script language="JavaScript" type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script language="JavaScript" type="text/javascript" src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script language="JavaScript" type="text/javascript" src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>

<script>
function showModal(modalSeletor) {
$(modalSeletor).modal({
    show: true
});
};
</script>

<apex:form >
<apex:actionRegion >
<div id="contacts" style="padding:20px;">
<table id="studentList" style="width:100%">
    <tr>
        <td style="width:25%;"><h1 class="heading">Contacts</h1></td>
        <td style="width:10%;padding-right:10px;"><button type="button" disabled="disabled" class="btn btn-default pull-right" style="height:40px">New Contact</button></td>
        <td style="border-left:2px solid #c0c0c0;padding-left:10px;">
            <ul class="nav nav-pills" role="pillList">
                <li role="presentation" class="active nav-pill"><a href="#" aria-controls="" role="tab" data-toggle="tab">All Contacts&nbsp;<span class="badge">{!getContacts.size}</span></a></li>
            </ul>
        </td>
    </tr>
</table>

<hr/>


<table class="table table-striped portalTable" style="width:100%;">
    <thead>
        <tr><td>Contact Name</td><td>Phone</td><td>Owner</td><td>Action</td>
</tr>
    </thead>
    <tbody>
    <apex:repeat value="{!getContacts}" var="con">
        <tr><td>{!con.firstName}&nbsp;{!con.lastName}</td><td>{!con.phone}
</td><td>{!con.owner.name}</td>
        <td><button type="button" class="btn btn-blue" data-toggle="modal" onclick="viewConModal('{!con.id}','{!con.name}');">View Contact</button></td>
</tr>
    </apex:repeat>
    </tbody>
</table>

<apex:actionFunction name="viewConModal" action="{!getConDetails}" oncomplete="showModal('#viewConModal');" rerender="viewConBody,viewConNotBody">
    <apex:param name="selectedConId" assignTo="{!selectedConId}" value="" />
    <apex:param name="selectedConName" assignTo="{!selectedConName}" value="" />
</apex:actionFunction>

</div>
</apex:actionRegion>




<!--FIRST MODAL - CONTACT-->
<apex:actionRegion >
<div class="modal fade" id="viewConModal" role="dialog" tabindex="-1">
<div class="modal-dialog modal-md">
    <div class="modal-content">

        <apex:outputPanel layout="block" styleClass="modal-header">
            <button type="button" class="close" data-dismiss="modal">&times;
</button>
        </apex:outputPanel>

        <apex:outputPanel layout="block" styleClass="modal-body" id="viewConBody">
        <apex:repeat value="{!conDetails}" var="con">
        <h1>Details</h1>
        Name=<apex:outputField value="{!con.firstName}"/> <br/>
        ID=<apex:outputField value="{!con.id}"/>
        </apex:repeat>
        <h1>Notes</h1>

                <table>
                    <tr>
                        <td style="width:10%;padding-right:10px;">
                            <apex:commandbutton styleClass="btn btn-default pull-right" style="height:40px" html-data-toggle="modal" onclick="newNot('{!conDetails.id}','{!conDetails.name}');" reRender="newNotBody" value="New Note" />
                            <apex:actionFunction action="{!addConNote}" name="newNot" oncomplete="showModal('#newNotModal');" reRender="newNotBody">
                                    <apex:param name="selectedConId" assignTo="{!selectedConId}" value="" />
                                    <apex:param name="selectedConName" assignTo="{!selectedConName}" value="" />
                            </apex:actionFunction>
                        </td>
                        <td style="border-left:2px solid #c0c0c0;padding-left:10px;">
                            <ul id="notTabs" class="nav nav-pills" role="pillList">
                                <li role="presentation" class="active nav-pill"><a href="#note" aria-controls="note" role="tab" data-toggle="tab">Note 
<span class="badge">{!contactNotes.size}</span></a></li>
                            </ul>
                        </td>
                    </tr>
                </table>

                <hr/>

                <div class="tab-content">

                    <div role="tabpanel" class="tab-pane fade in active" id="note">
                        <table class="table table-striped portalTableModal" style="width:100%;" id="stuNotes">
                            <thead class="tableHeadBlue">
                                <tr>
                                    <td>Title</td>
                                    <td>Action</td>
                                </tr>
                            </thead>
                            <tbody>
                            <apex:repeat value="{!contactNotes}" var="conNot">
                                <tr>
                                    <td><apex:outputText value="{!conNot.title}"/></td>
                                    <td><apex:outputText value="{!conNot.body}"/></td>
                                </tr>
                            </apex:repeat>
                            </tbody>
                        </table>
                    </div>

                </div>

        </apex:outputPanel>

        <apex:outputpanel layout="block" styleClass="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        </apex:outputPanel>

    </div>
</div>
</div>




<!--SECOND MODAL - NEW NOTE-->

<div class="modal fade" id="newNotModal" role="dialog">
<div class="modal-dialog">
    <div class="modal-content">

        <apex:outputPanel id="newConNotHeader" layout="block" styleClass="modal-header modal-header-blue">
            <button type="button" class="close" data-dismiss="modal">&times;</button>
            <h3 class="modalHeader"><span class="glyphicon glyphicon-list"/>&nbsp;&nbsp;New Note</h3>
        </apex:outputPanel>

        <apex:outputPanel id="newNotBody" layout="block" styleClass="modal-body">

        selectedConId ID {!selectedConId}

            <table class="modalDetail" style="width:100%;">
                <tr>
                    <td colspan="2">
                    <div class="form-group">
                        <label class="control-label label-form" for="notTitle">Title</label>
                        <div class="input-group">
                            <div class="input-group-addon">
                                <span class="glyphicon glyphicon-pencil" aria-hidden="true"/>
                            </div>
                            <apex:inputField id="notTitle" value="{!addConNote.title}" styleClass="form-control" required="true"  html-placeholder="Title"/>
                        </div>
                    </div>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                    <div class="form-group">
                        <label class="control-label label-form">Body</label>
                        <div class="input-group">
                            <div class="input-group-addon">
                                <span class="glyphicon glyphicon-pencil" aria-hidden="true"/>
                            </div>
                            <apex:inputTextarea value="{!addConNote.body}" style="resize:none;" html-placeholder="Body" rows="10" styleClass="form-control"/>
                        </div>
                    </div>
                    </td>
                </tr>
            </table>
        </apex:outputPanel>

        <apex:outputpanel id="newConNotFooter" layout="block" styleClass="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

            <apex:commandbutton styleClass="btn btn-default" html-data-dismiss="modal" value="Create Note" onclick="addNote('{!selectedConId}','{!selectedConName}');" reRender="newConNotBody,newConBody">

            <apex:actionFunction action="{!addConNote}" name="addNote" reRender="newConNotBody">
                <apex:param name="selectedConId" assignTo="{!selectedConId}" value="{!selectedConId}" />
                <apex:param name="selectedConName" assignTo="{!selectedConId}" value="{!selectedConName}" />
            </apex:actionFunction>

            </apex:commandButton>
        </apex:outputpanel>

    </div>
</div>
</div>
</apex:actionRegion>
</apex:form>

</apex:page>

APEX:

public with sharing class modalCreateRecord {

public list <contact> getContacts {get;set;}
public Id selectedConId {get;set;}
public String selectedConName {get;set;}

public Contact conDetails {get;set;}
public Note conNotDetails {get;set;}
public Note addConNote {get;set;}
public list <Note> contactNotes {get;set;}

    public modalCreateRecord(){
        getContacts = [SELECT name,id,owner.name,firstName,lastName,phone FROM Contact ORDER BY createdDate LIMIT 10];
        addConNote = new note(
            OwnerId = UserInfo.getUserId(),
            //ParentId = selectedConId
            ParentId = '003O000000yaKB6IAM'
        );
    }

    public void getConDetails(){
        conDetails = [SELECT Id,Name,FirstName,owner.name FROM contact WHERE id = :selectedConId LIMIT 1];
        getContactNotes();
    }

    public void getContactNotes(){contactNotes = [SELECT Id, Body, title FROM Note WHERE parentID = :selectedConId ORDER BY createdDate desc];}
    public void getConNotDetails(){conNotDetails = [SELECT id,Body,parent.id,Title FROM note WHERE id = :selectedConId LIMIT 1]; }


    public PageReference addConNote() {
        try {     
            insert (addConNote);
            addConNote = null;
            return null;
        } 
        catch(System.Exception e) {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error Creating Note.'));
        }
        return null;
    }
}
1

Mixing JavaScript and Visualforce is usually a challenging endeavor, as it seems that the smallest thing can cause everything to go awry. I can't seem to fully fix your code in my dev org, but I'll address the issues I've found so far. In the future, you might try to make shorter, more concise examples; we usually prefer one question per question. That said, here we go:


apex:form

Don't use more than one form per page. Communication across forms does not happen. Not only does it restrict communication, it also drastically increases view state size, risking the odds you'll run into governor limits. Put the apex:form around the entire page (e.g. start immediately after your scripts and includes, and end immediately before the end of the page).

Rerender the Entire Form

If you target only certain elements, you'll also only submit certain pieces of data. This causes subtle errors because not the entire view state is transmitted.

Use JSINHTMLENCODE

If your contact's name has an odd symbol in it, you might break your page's code. Make sure you're encoding the name:

{!JSINHTMLENCODE(con.Name)}

Track non-Visualforce JS State

When you're trying to show a double-modal, you're going to need to keep track of the current state of the page, because Visualforce doesn't know about DOM modifications you're making. This is tied to the earlier suggestion that you rerender the entire form. You need more JavaScript.

addConNote Changes

Assuming your selectedConId were working, you'd need to assign it before inserting the note. Also, once you've saved okay, you need to clear out your fields.

public void addConNote() {
    addConNote.ParentId = selectedConId;
    Database.InsertResult result = Database.insert(addConNote);
    if(result.isSuccess()) {
        addConNote.Title = null;
        addConNote.Body = null;
    }
}

Even after all these changes, I still wasn't able to get things working 100%. You might be better off going with a pure JavaScript implementation and skipping the controller entirely. You can use apex:remoteObjects to query, insert, and update records, and render your page using pure jQuery. You'll get better performance and better control over your page. Alternatively, drop the JavaScript and go with pure Visualforce instead. This would be really easy to do if you dropped all of the jQuery and went with pure Visualforce instead.

  • Thanks for your response. Multiple forms - I need to use multiple forms, and I understand the need to communicate (variables, re-render etc), which is why I need a JS solution. Basically I have this working until the final ID issue (issue 1), I can even get to the point where i don't need to refresh the page to get the new note list to repopulate, by closing both modals and selecting the contact again. I suspect the solution is out there, and its mostly JS! – TheMikeyBoosh May 1 '17 at 3:03
  • @TheMikeyBoosh Using multiple forms may run into issues. The documentation says that, the security scanner flags it. You can ignore the advice, surely, but don't say you weren't warned. And yes, you can do this mostly pure JS, but you're not doing mostly JS, you're in a halfway hybrid state that's very difficult to code in. My suggestion is to go full-on JS or full-on VF, and avoid mixing the two. It's a lot more effort than it's worth. – sfdcfox May 1 '17 at 3:17
  • So you're saying you don't know how to pass the original contact ID through to the addConNote function? – TheMikeyBoosh May 1 '17 at 3:35
  • @TheMikeyBoosh It should be present in the selectedConId variable, but the way your code is structured, it's getting lost somehow. I've used similar techniques in the past without an issue, but only using a single form. You also have other issues, like how your error messages won't display because the modal closes even if there's a save error. – sfdcfox May 1 '17 at 3:41
  • 1
    Let us continue this discussion in chat. – sfdcfox May 1 '17 at 4:10
0

I have had some help on this issue locally! As it turns out, there is a simple change to the controller which fixes this issue (id being passed after record creation) and also refreshes the form...

public Id addConNotId {get;set;}

public PageReference addConNote() {
        try {     
            addConNote.ParentId = selectedConId;
            addConNote.OwnerId = UserInfo.getUserId();
            insert(addConNote);
            addConNotId = addConNote.Id;
            addConNote = null;
        return null;
        } 
        catch(System.Exception e) {
            ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error Creating Note.'));
        }
        return null;
    }

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.