3

I am facing with the problem, that when user inserts into text field "\" char and this field has inline edit functionality it breaks the whole page, table structure breaks also if this field is inside some pageBlockTable

Part of vf page:

    <apex:pageBlockTable id="tabTable" value="{!tabs}" var="tab">
          <apex:column headerValue="Name" >
            <apex:outputField value="{!tab.Name}" rendered="{!tab.Id != null}" >
                <apex:inlineEditSupport event="ondblClick" />
            </apex:outputField>
            <apex:inputField value="{!tab.Name}" rendered="{!tab.Id == null}" />
          </apex:column> 

I added some methods into controller, which remove this char, but as ui is broken it doesnt refresh the page. So user should refresh it manually or click "Save" again.

Clean method:

public static SObject cleanRecordStringFields(SObject record) {

    if (record != null) {

        List<DescribeFieldResult> stringFields = getStringFieldsOfRecord(record);

        //sanitize string fields
        for (DescribeFieldResult field : stringFields) {

            String fieldValue = (String) record.get(field.getName());

            if ( String.isNotBlank( fieldValue ) ) {

                String sanitizedString = sanitizeStringValue(fieldValue);

                //check field's max length
                sanitizedString = sanitizedString.length() > field.getLength() 
                                    ? sanitizedString.substring(0, field.getLength()) : sanitizedString; 

                record.put( field.getName(), sanitizedString );

            }

        }

    }

    return record;
} 

Any beautiful solution to this situation? I thought to add some field validation in controller, but as we have a lot of objects with text fields and i cannot use addError() with dynamic apex, its a pain to add to each field validation and maintain this in future :(

Adrian Larson
  • 149,971
  • 38
  • 239
  • 420
Bogdan K
  • 704
  • 2
  • 7
  • 15

2 Answers2

3

If the problem occurs somewhere during the roundtrip between the client and server, then validating on the server side may be too late. Here's an example of how you could do it via Javascript. You should be able to package this up in a Static Resource and include it anywhere you use inlineEditSupport.

(function (D, w) {
    "use strict";
    D.addEventListener('DOMContentLoaded', function () {
        var i, inputs = D.getElementsByTagName('input'),
            sanitize = function (event) {
                if (String.fromCharCode(event.which) == '\\') {
                    event.preventDefault();
                }
            },
            observer = new MutationObserver(function (mutations) {
                mutations.forEach(function (mutation) {
                    var nodes = mutation.addedNodes;
                    if (nodes.length > 0 && nodes[0].tagName == 'INPUT') {
                        nodes[0].addEventListener('keypress', sanitize);
                    }
                });
            });
        observer.observe(D.body, { childList: true, subtree: true });
    });
}(document, window));
Adrian Larson
  • 149,971
  • 38
  • 239
  • 420
  • haha, this is great! I just cant insert this char now! Thanks a lot! Question: can you suggest any books\blogs where i can dig into functionality of standard sf UI (get js it uses, extend it, etc) – Bogdan K Aug 09 '16 at 11:05
  • @Cooler are you asking about http://salesforce.stackexchange.com/questions/38918/end-of-javascript-sidebar-workarounds? – Adrian Larson Aug 09 '16 at 13:23
  • Yeah, something like that. btw, after of some test, found that with copy paste we can put data with \ . Any suggestions, how to prevent this too, is there any other eventListener for copy paste? – Bogdan K Aug 09 '16 at 20:23
  • Hmm, yeah you could use a change listener instead, you'd just need to do a regex find and replace. Lots of [so] posts cover that piece, I imagine. – Adrian Larson Aug 09 '16 at 20:24
1

The final solution is:

(function (D, w) {
    "use strict";
    D.addEventListener('DOMContentLoaded', function () {
            var sanitize = function (event) {
                event.target.value = event.target.value.replace(/\\/g, '');                 
            },
            observer = new MutationObserver(function (mutations) {
                mutations.forEach(function (mutation) {
                    var nodes = mutation.addedNodes;
                    if (nodes.length > 0 && (nodes[0].tagName == 'INPUT' || nodes[0].tagName == 'TEXTAREA') ) {
                        nodes[0].addEventListener('input', sanitize); 
                    }
                });
            });
        observer.observe(D.body, { childList: true, subtree: true });
    });
}(document, window));
Adrian Larson
  • 149,971
  • 38
  • 239
  • 420
Bogdan K
  • 704
  • 2
  • 7
  • 15
  • You should probably do the replace in a separate listener. You could theoretically change the form value without a keypress. – Adrian Larson Aug 09 '16 at 21:58
  • And it is not the end)) If you copy paste data with backslash and after that push Enter key, it will not work, playing with listeners second hour and no luck :( – Bogdan K Aug 10 '16 at 19:27
  • Maybe blur would be best. Or you could add a submit listener on the form. – Adrian Larson Aug 10 '16 at 19:28
  • blur doesnt work also, looks like event value changes, but too late, filled data stays with backslash, but console log return clean data. Submit listener? Can you show an example how you think to use it here? – Bogdan K Aug 10 '16 at 19:42
  • I still think onchange is the most likely event to work for you. Did you try that one? – Adrian Larson Aug 10 '16 at 19:55
  • Yes, i think the problem is, that vf has some priority on Enter key for inline edit. Looks like, when i hit Enter, we fetch data as is and after that our listener runs and its functionality is not related any more to the inlineEdit – Bogdan K Aug 10 '16 at 19:58
  • 1
    got it :) input listener is what we need. Many thanks to you Adrian – Bogdan K Aug 10 '16 at 21:00