Re: Making Form Fields Read Only

Amy_Lepre
Level 7

With Forms 1.0, I had some custom code (largely written by someone else in the community, not me) that allowed me to display the value of form fields, but make the fields themselves read-only so the values couldn't be changed upon form submission. This same code won't work for Forms 2.0. Has anyone done something like this and are you willing to generously share the code you used to make it happen? 🙂

19 REPLIES 19
Chris_Johnston
Level 8

Hi Amy, I am super interested in what your use case is for this? My initial thoughts are, why don't you just use Tokens to display this information on the Landing Page and declutter the form? Either way, I am sure there are tons of generous people here on the Forms who might be able to help you out. I work with a team of developers, and the code isn't overly complicated, and if you aren't able to find some to replicate, our team would be happy to help you (although perhaps less generously than you were hoping for).

Amy_Lepre
Level 7

Hi Chris,

Here's our use case:

We have a distributor network that sells our line of products. When leads that we've identified as belonging to our distributors come to our website and/or landing pages and generate enough activity to push their lead score over a certain threshold, we send the distributor an alert with the lead information and activity. We then ask them to provide feedback on the lead by means of a link in the email that contains a querystring with token values to populate the form fields in the landing page. We don't want the distributors to change the lead information, just want it to display so they can see they're providing feedback on the right person. I don't believe (trust) that the token on the landing page would work since the distributor's own cookied information may show instead of the lead's information. I'm certainly open to other ideas, but am going to take a look at what Sanford provided below to see if that works for me.

Thanks for your response!

SanfordWhiteman
Level 10 - Community Moderator

I don't believe (trust) that the token on the landing page would work since the distributor's own cookied information may show instead of the lead's information.

You're correct about this.

But what you didn't explain before is that the fields are being filled from the query string. In Forms (1.0 and 2.0) this isn't native behavior because only hidden fields are filled from the query. Therefore you need to parse the query string as well.  I added that functionality to expanded CodePen. You can use uri.js as included in the HTML pane here: MktoForms2 :: Lock URL-Filled Fields

My_Nguyen
Level 2

I came across an issue where a plus symbol in someone's email address causes this to input an invalid email in the email field because it turns into a space. Do you know of a way to fix that?

SanfordWhiteman
Level 10 - Community Moderator

The plus sign should already be URI-encoded (as %2B).  That's how you put an email address with a plus sign in a URL in the first place.

My_Nguyen
Level 2

The email address token was used to insert the email address into the link inside an email. Is there anything that can be done to make it automatically turn that plus sign into %2B?

SanfordWhiteman
Level 10 - Community Moderator

You have to use a Velocity token to URI-encode any content that isn't already URI-encoded. (Far too many many people ignore this, see another example in my comment here: )

My_Nguyen
Level 2

Is this correct for the email scripting token?

$esc.url(${lead.Email})

It seems like Marketo Sky keeps rewriting the code.

SanfordWhiteman
Level 10 - Community Moderator

Don't know what Sky would have to do with it?

You'd be adding within the Script Editor.

Make sure you check off the lead.Email field in the tree on the right-hand side of the editor.

And you need to output the entire link from the Velocity code (this is always the case) not just the URL:

<a href="https://www.example.com/?email=${esc.url($lead.Email)}">link text</a>
SanfordWhiteman
Level 10 - Community Moderator

why don't you just use Tokens to display this information on the Landing Page and declutter the form

This won't work if the intent (as it usually is) is to make a field read-only if it currently has a value. Thus it needs to be a form <input>, not simple text, so it can serve both purposes.

Dan_Stevens_
Level 10 - Champion Alumni

Sandy, I really enjoy reading all of the solutions you provide to address ways to extend the functionality of forms.  But what's still difficult to comprehend is how to deploy these solutions in our existing guided LP environment, using our primary LP template.  Since you're no longer to add custom HTML code blocks like you were able to with free-form LPs, all of the customization must be done at the template level.  So does this mean we need to create yet another template each and every time we want to extend the functionality of forms on our LPs?

Courtney Grimes​ submitted this great idea a few months back:

According to this idea (also submitted by Courtney) - - this functionality is "coming soon" (I'm just not sure when Marketo PMs marked this as such).

SanfordWhiteman
Level 10 - Community Moderator

So does this mean we need to create yet another template each and every time we want to extend the functionality of forms on our LPs?

I definitely wouldn't say that!

I always include custom form behaviors in external <script> tags, then enable and disable them using mktoBoolean variables. 

In many cases the behaviors are self-enabling, that is, if they only pertain to a given form ID then they'll be ignored for other forms, or if they only pertain to a given field they'll be skipped over if that field doesn't exist.

Dan_Stevens_
Level 10 - Champion Alumni

Justin provided an update here: https://nation.marketo.com/ideas/7175#comment-32731

SanfordWhiteman
Level 10 - Community Moderator

Very simple for text and text-like fields (input[type="text"], input[type="email"], etc.) -- see MktoForms2 :: Lock Filled Fields

For sets like checkboxes it's a little more complex. Let me know if that's something you're currently doing.

Amy_Lepre
Level 7

Hi Sanford,

Thanks for your response. I tried a couple of ways to put this JS into my guided landing page, but I get an unexpected (for me) response - my form shows up on the page twice, with the first form working to make the fields read only and the second form not doing that. The method I'm using now is I have a script block on the landing page, as set in the template like this:

   <div class="mktoText" mktoname="Script" id="Script">

     </div>

I added the JS like so, changing the variable information to ours:

<script type="text/javascript">

var instanceURL = "//app-abb.marketo.com",

munchkinId = "599-FFU-113",

formId = 3144;

MktoForms2.loadForm(instanceURL, munchkinId, formId);

MktoForms2.whenRendered(function(form) {

/* array of  the fields you want to mark read-only */

var lockFilledFields = ["FirstName", "Email"];

/* ---- NO NEED TO EDIT BELOW THIS LINE! ---- */

var formEl = form.getFormElem()[0];

lockFilledFields

.map(function(fieldName) { // names to selector

return '[name="' + fieldName + '"]:not([data-rendered="true"])';

})

.map( // stor to collection

formEl.querySelectorAll, formEl

)

.forEach(function(els) { // mark all and set readOnly if filled

[].slice.call(els).forEach(function(el) {

el.setAttribute("data-rendered", "true");

if (el.value != "" ) {

el.readOnly = true;

}

});

});

});

</script>

Marketo does insert this after the opening script tag:

// <![CDATA[

I tried putting the code in the custom head HTML section, but that seemed to have no effect at all. Hopefully it's just a simple user error on my part that's causing the form to show up twice on the landing page. Any ideas?

SanfordWhiteman
Level 10 - Community Moderator

Also, if you can move this whole thread to Products​ that would be better (it's supposed to be there b/c it's Marketo-product-specific).

SanfordWhiteman
Level 10 - Community Moderator

Thanks for your response. I tried a couple of ways to put this JS into my guided landing page, but I get an unexpected (for me) response - my form shows up on the page twice, with the first form working to make the fields read only

It shows up twice because you're probably calling ​loadForm​ twice!

If you already have a named Form element on a Marketo LP, or already have the embed code on a non-Marketo LP, you just need the part that starts with

MktoForms2.whenRendered(function(form) {

My CodePen necessarily includes the loadForm call at the top. You don't need to do that again.

Also, when pasting code here, ​please ​use syntax highlighting.

pastedImage_3.png

pastedImage_4.png

It's not readable otherwise.

Amy_Lepre
Level 7

FYI - here is the code that I was using on the old landing page (non-guided) using a Forms 1.0 form.

This reminds me there is a second part to this, where we saw an issue in the past with any spaces in the querystring coming into the form with the URL encoded format of %20.

<script language="Javascript" src="/js/public/jquery-latest.min.js" type="text/javascript"></script>

<script src="/js/public/jQueryString-2.0.2-Min.js" type="text/javascript" ></script>

<script>

  // to set cookies.  Uses noConflict just in case

var $jQ = jQuery.noConflict();

var pEmail = decodeURIComponent($jQ.getQueryString({ ID: "Email" }));

var pFirstName = decodeURIComponent($jQ.getQueryString({ ID: "FirstName" }));

var pLastName = decodeURIComponent($jQ.getQueryString({ ID: "LastName" }));

var pCompany = $jQ.getQueryString({ ID: "Company" });

var pCountry = $jQ.getQueryString({ ID: "Country" });

var pCompiled_Lead_Feedback__c = $jQ.getQueryString({ ID: "Compiled_Lead_Feedback__c" });

var p_mkt_trk = $jQ.getQueryString({ ID: "_mkt_trk" });

pFirstName=pFirstName.replace(/%20/g," ");

pLastName=pLastName.replace(/%20/g," ");

pCompany=pCompany.replace(/%20/g," ");

pCountry=pCountry.replace(/%20/g," ");

pCompiled_Lead_Feedback__c=pCompiled_Lead_Feedback__c.replace(/%20/g," ");

document.getElementById("Email").setAttribute("value", pEmail);

document.getElementById("FirstName").setAttribute("value", pFirstName);

document.getElementById("LastName").setAttribute("value", pLastName);

document.getElementById("Company").setAttribute("value", pCompany);

document.getElementById("Country").setAttribute("value", pCountry);

document.getElementById("Compiled_Lead_Feedback__c").setAttribute("value", pCompiled_Lead_Feedback__c);

document.getElementById("Compiled_Lead_Feedback__c").value = pCompiled_Lead_Feedback__c;

document.getElementById("_mkt_trk").setAttribute("value", p_mkt_trk);

$jQ(document).ready(function() {

poller = setInterval(function(){

if($jQ('#Email').val().length >= 1)

{ $jQ('#Email').prop('readonly', true); clearInterval(poller);

  $jQ('#FirstName').prop('readonly', true); clearInterval(poller);

  $jQ('#LastName').prop('readonly', true); clearInterval(poller);

  $jQ('#Company').prop('readonly', true); clearInterval(poller);

    $jQ('#Country').prop('readonly', true); clearInterval(poller);

  $jQ('#Compiled_Lead_Feedback__c').prop('readonly', true); clearInterval(poller);

}

}, 500);

});

</script>

SanfordWhiteman
Level 10 - Community Moderator

Wow, new winner, worst form code contest.   Can you delete the post with the Forms 1.0 code so no one copies it? Thanks.