SOLVED

Re: Marketo form checkbox styling issue

Go to solution
Yavor_Todorov
Level 3

Hello,

on this page https://info.softwareag.com/test-form-checkboxes.html, on the right side with the form, I have checkboxes(Question_1), where the actual square is aligned to its label on the same line.

But if I use a single checkbox(I opt in), the square moves to the next line. I want to move it just before "I opt in" text on the same line, like it's visualised for Question_1.

Looks like an easy CSS fix, but I cannot figure it out.

 

Thanks a lot,

Yavor

 

 

 

1 ACCEPTED SOLUTION
SanfordWhiteman
Level 10 - Community Moderator

The sample seems to work, but not in all cases.

Works in all cases that you originally described, since you didn't mention VRs. 🙂

 

If you have VRs you need to use a different event and also add a guard:

MktoForms2.whenRendered(function(mktoForm){
   /* the Checkbox field/s you want to alter */
   const singleCheckboxAsMultiple = ["question2"];

   /* no need to touch below this line */
   let formEl = mktoForm.getFormElem()[0];   
   singleCheckboxAsMultiple.forEach(function(fieldName){
      let checkbox = formEl.querySelector("input[name='" + fieldName + "']"),
          primaryLabel = formEl.querySelector("label[for='" + checkbox.id + "'].mktoLabel"),
          secondaryLabel = formEl.querySelector("label[for='" + checkbox.id + "']:not(.mktoLabel)");

      if(primaryLabel.getAttribute("data-content-migration-state") !== "done"){
        secondaryLabel.innerHTML = primaryLabel.innerHTML;
        primaryLabel.innerHTML = "";
        primaryLabel.setAttribute("data-content-migration-state", "done");
      }
   });
});

 

View solution in original post

13 REPLIES 13
Disha_Goyal6
Level 6

Hi @Yavor_Todorov,

 

You can achieve the desired result by using the below CSS

.mktoFieldWrap {
    display: flex;
    flex-wrap: wrap;
}
label#LbltemporaryEmailOptIn {
    order: 2;
}
.mktoGutter.mktoHasWidth {
    display: none;
}
.mktoForm .mktoFormRow .mktoRadioList, .mktoForm .mktoFormRow .mktoCheckboxList {
    width: auto !important;
    padding: 0 !important;
    float: left !important;
    margin-top: -5px !important;
}

 

Thanks,

Disha

Dave_Roberts
Level 10

Just use the "checkboxes" field type, even if you only need it for one field in the set. Then you can set it up just like you've got the other checkboxes field on the form and don't need any fancy CSS or JS. 


Out of curiosity, what is the reason you're changing it to a "checkbox" field type instead of a "checkboxes" field type?

SanfordWhiteman
Level 10 - Community Moderator

Dave, the specific reason I didn’t make that suggestion is that a Checkboxes set with a single checkbox isn’t supposed to behave the same way as a Checkbox.

 

There is currently a bug (I’ve written about it before) that makes the forms library behave as you want here. But it’s a bug that may be fixed at any time, so you can’t rely on it. When it’s fixed, your form breaks.

 

By design, a Checkbox manages a boolean field in both directions, sending “yes” if it’s checked and “no” if it’s unchecked. This works reliably.

 

By design, a checkbox within a Checkboxes set is different. It sends a value if it’s checked, but it will not send a value if it’s unchecked — thus leaving the server value as-is.

 

But due to a coincidental bug, if you have a single checkbox within a Checkboxes set and its value is “yes”, the library misinterprets the original type as being Checkbox. (Rather than consulting the actual type checkbox as it should, it duck-types the field and guesses it’s a single_checkbox based on the value attribute.) It then proceeds as if it were a Checkbox with the two possible values “yes” and “no”. But again, this isn’t supposed to be the case. The Checkboxes value “yes” should be no different than “yass”.

Dave_Roberts
Level 10

Thanks for the explanation here, appreciate it. Any idea when/if this bug is going to get addressed? 

SanfordWhiteman
Level 10 - Community Moderator

Can’t say. Probably not until there’s another major version of the library? But I’m sure it wasn’t not intentional.

 

Btw to work around it and have a Checkboxes set work as it should with only one visible checkbox, add a second checkbox (it doesn’t matter what value it has, no one will ever see it) and hide it with CSS:

/* hide extra checkbox used to fix checkboxes bug */
.mktoForm .mktoLabel[for="Unsubscribed"] ~ div input:not(:first-child),
.mktoForm .mktoLabel[for="Unsubscribed"] ~ div input:not(:first-child) ~ label {
  display: none;
}

 

Since there’s more than one checkbox in the DOM, even if not shown to the end user, Marketo won’t accidentally treat the set as a single. Now if the checkbox is unchecked the server value will be untouched.

SanfordWhiteman
Level 10 - Community Moderator

If you want the same layout for a single checkbox (Checkbox type) as you get with a multiple checkbox set (Checkboxes type), you don’t need to change CSS.

 

There’s only one fundamental difference in the HTML and that’s which label(s) have inner content. In the case of the Checkbox the label after the checkbox is empty.

 

You can simply move the text from the “title” label (above the field) to the checkbox-specific label (after the field) using JS:

MktoForms2.whenReady(function(mktoForm){
   /* the Checkbox field/s you want to alter */
   const singleCheckboxAsMultiple = ["question2"];

   /* no need to touch below this line */
   let formEl = mktoForm.getFormElem()[0];   
   singleCheckboxAsMultiple.forEach(function(fieldName){
      let checkbox = formEl.querySelector("input[name='" + fieldName + "']"),
          primaryLabel = formEl.querySelector("label[for='" + checkbox.id + "'].mktoLabel"),
          secondaryLabel = formEl.querySelector("label[for='" + checkbox.id + "']:not(.mktoLabel)");

      secondaryLabel.innerHTML = primaryLabel.innerHTML;
      primaryLabel.innerHTML = "";
   });
});

 

That changes the layout as shown:SanfordWhiteman_0-1660364868779.png

Yavor_Todorov
Level 3

Thanks @SanfordWhiteman

The sample seems to work, but not in all cases. Here is an example: https://info.softwareag.com/test-form-checkboxes.html

Sometimes, not every time, when I type First/Last/Email or reselect a Country, the JS seems to fail and makes the "Temporary Email Opt In" checkbox go to a new line like:

chrome_9M7UiDKGTy.png

After some investigations it seems that the "Temporary email Opt In" has visibility rules, it hides if for ex. USA is selected as a Country.  So:

1. If I select USA the box dissapears, this is good.

2. Then if I select another country, the checkbox drops to a new line. 

 

Can we refactor the JS in some way so it works after Visibility rules take effect?

 

Thanks,

Yavor

SanfordWhiteman
Level 10 - Community Moderator

The sample seems to work, but not in all cases.

Works in all cases that you originally described, since you didn't mention VRs. 🙂

 

If you have VRs you need to use a different event and also add a guard:

MktoForms2.whenRendered(function(mktoForm){
   /* the Checkbox field/s you want to alter */
   const singleCheckboxAsMultiple = ["question2"];

   /* no need to touch below this line */
   let formEl = mktoForm.getFormElem()[0];   
   singleCheckboxAsMultiple.forEach(function(fieldName){
      let checkbox = formEl.querySelector("input[name='" + fieldName + "']"),
          primaryLabel = formEl.querySelector("label[for='" + checkbox.id + "'].mktoLabel"),
          secondaryLabel = formEl.querySelector("label[for='" + checkbox.id + "']:not(.mktoLabel)");

      if(primaryLabel.getAttribute("data-content-migration-state") !== "done"){
        secondaryLabel.innerHTML = primaryLabel.innerHTML;
        primaryLabel.innerHTML = "";
        primaryLabel.setAttribute("data-content-migration-state", "done");
      }
   });
});

 

Yavor_Todorov
Level 3

Thanks @SanfordWhiteman,

the VR code works fine, however we want to not just show it for one or two checkboxes on the page

const singleCheckboxAsMultiple = ["temporaryEmailOptIn", "immediateProjectNeed"];

We want to make this code work for each input[type=checkbox] on the page. Is there a way to achieve this?

Thanks,

Yavor

SanfordWhiteman
Level 10 - Community Moderator

Select all the matching elements.

MktoForms2.whenRendered(function(mktoForm){
   const arrayify = getSelection.call.bind([].slice);

   let formEl = mktoForm.getFormElem()[0];   

   /* the Checkbox field/s you want to alter */
   const singleCheckboxAsMultiple = arrayify(formEl.querySelectorAll("input[type='checkbox']")).map(function(el){
     return el.name;
   });

   /* no need to touch below this line */
   singleCheckboxAsMultiple.forEach(function(fieldName){
      let checkbox = formEl.querySelector("input[name='" + fieldName + "']"),
          primaryLabel = formEl.querySelector("label[for='" + checkbox.id + "'].mktoLabel"),
          secondaryLabel = formEl.querySelector("label[for='" + checkbox.id + "']:not(.mktoLabel)");

      if(primaryLabel.getAttribute("data-content-migration-state") !== "done"){
        secondaryLabel.innerHTML = primaryLabel.innerHTML;
        primaryLabel.innerHTML = "";
        primaryLabel.setAttribute("data-content-migration-state", "done");
      }
   });
});
Yavor_Todorov
Level 3

Thanks @SanfordWhiteman, you are amazing! It works, but I still see one case when it breaks 😞 

It's when I have checkboxes and checkbox on a page at the same time, as here - https://info.softwareag.com/test-checkboxes.html

This error appears in the console: Cannot read properties of null (reading 'getAttribute')  on this line

if(primaryLabel.getAttribute("data-content-migration-state") !== "done")

 

Thanks once again for your brilliant support!

SanfordWhiteman
Level 10 - Community Moderator

You can change the selector to whatever you want.

Raven_McFarlan1
Level 3

Hey Yavor! Got to love forms! 🙂 I looked into your lp-form style sheet. It seems like removing width: 100% !important; (from the section seen below, line 75 I believe) allows the checkbox to display on the same line. 

}

.mktoForm .mktoRadioList, .mktoForm .mktoCheckboxList {
    width: 100% !important;
    padding: 0 !important;
    float: inherit !important;
}

 

This won't however ensure this checkbox is aligned with those above it. Wasn't sure if you planned on retaining both, but let me know if I can take another look 🙂 Hope this helps!!