Thursday, 23 July 2015

Semantic UI form validation on SalesForce

I spent a couple of hours trying to figure this out this morning so I though it would be worth documenting. When you use apex:inputText within SalesForce there are all sorts of extra stuff added to the id and name, as long as you use apex:outputLabels with the correct for and value values then all is gravy as the labels and inputs match. So markup like this:

<div class="two fields">
    <div class="eight wide field">
        <apex:outputLabel for="firstName" value="First Name"/>
        <apex:inputText value="{!firstName}" id="firstName"/>
    </div>
    <div class="eight wide field">
        <apex:outputLabel for="lastName" value="Last Name"/>
        <apex:inputText value="{!lastName}" id="lastName"/>
    </div>
</div>

Will produce this HTML:

<div class="two fields">
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:firstName">First Name</label>
        <input id="somePageName:someTemplate:someForm:firstName" type="text" name="somePageName:someTemplate:someForm:firstName"/>
    </div>
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:lastName">Last Name</label>
        <input id="somePageName:someTemplate:someForm:lastName" type="text" name="somePageName:someTemplate:someForm:lastName" />
    </div>
</div>

Which is cool for most things as, if you need to reference the field with jQuery you can use:

$("input[id$='firstName']")

Or in regular JavaScript:

document.querySelector("input[id$='firstName']")

But Semantic UI form validation matches against either the name, id or the data-validate attributes. I know from experience that, coming from doing lots of jQuery, I wanted to get the id and add that... perhaps using something like this:

document.querySelector("input[id$='firstName']").id

To pass the generated id to the validation rules for the identifier... don't go that route though, it'll only lead to madness!!!

Rather use the data-validate by adding html-data-validate to the apex:inputText. It's much more readable and will make things ever-so-much easier on you:

<div class="two fields">
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:firstName">First Name</label>
        <input id="somePageName:someTemplate:someForm:firstName" type="text" name="somePageName:someTemplate:someForm:firstName" html-data-validate="firstName"/>
    </div>
    <div class="eight wide field">
        <label for="somePageName:someTemplate:someForm:lastName">Last Name</label>
        <input id="somePageName:someTemplate:someForm:lastName" type="text" name="somePageName:someTemplate:someForm:lastName" html-data-validate="lastName"/>
    </div>
</div>

Really, it's much easier doing it this way and it will save you no end of headaches trying to remember the somePageName and someTemplate values.