0

I am adding a geolocation field to a simple visualforce page and controller extension which lets users set a few fields on their user record so I can use them in places using the $user global variable

The page works fine, but as longitude needs to be from -180 to 180, I'm trying to add a bit of validation to ensure that the value is within bounds.

I'm doing so by adding some validation to the pagereference method that updates the user. It seems like the controller is evaluating the value from the initial query, and not the value that is coming from the visualforce page.

The reason I believe this is that When I click save, with a value of 999 for longitude, I get a system error for "value outside of valid range on numeric field." If the IF statement was evaluating 999, it would be TRUE, and so the controller should just write to the debug log and do nothing.

Would appreciate guidance on the correct way to go about this. I tried to shorten the code snippets to just include the relevant bits of controller and visualforce page.

Controller (snippet)

public class UserControllerExtension {

    public UserControllerExtension(ApexPages.StandardController stdController) {
       }

    public user u = [SELECT Id,Location_For_Distance_Reporting__latitude__s, Location_For_Distance_Reporting__longitude__s, Location_Units__c From USER Where Id =:UserInfo.GetuserId()];

    public User getUser () {
         return u;
         } 

public PageReference saveChanges() {
     IF(math.abs ( u.Location_For_Distance_Reporting__longitude__s ) > 180){
         system.debug('error - longitude out of bounds');
     }
     ELSE {
      update u;

       }
        return null;
        }

Visualforce Page (snippet)

fwiw i'm looking at switching the whole thing to use apex:panelgrid, but got sidetracked by working on the field validation

<apex:page standardController="User" extensions="UserControllerExtension" sidebar="false" showHeader="false" showchat="false">

    <apex:pageBlock>
        <apex:pageBlockSection collapsible="false" columns="1" id="output">
            <span class="sectionType">Location Reporting Values</span>
            <apex:panelGrid style="width:62%; padding-top:5px; font-size:1em;" id="cSettings2" columns="2" columnClasses="colA,colB" rowClasses="rowA">
                <apex:outputLabel value="Location Name" />
                <apex:outputField value="{!User.Location_Name__c}" />
                <apex:outputLabel value="Distance Units (mi/km)" />
                <apex:outputField value="{!User.Location_Units__c}" />
                <apex:outputLabel value="Latitude" />
                <apex:outputField value="{!User.Location_For_Distance_Reporting__Latitude__s}" />
                <apex:outputLabel value="Longitude" />
                <apex:outputField value="{!User.Location_For_Distance_Reporting__Longitude__s}" />
            </apex:panelGrid>

        </apex:pageBlockSection>
        <apex:pageBlockSection columns="1" collapsible="false">
            <table style="width:85%; padding-top:5px;">
                <apex:form>

                    <tr>
                        <td>
                            <span class="sectionType">Location Reporting Values</span>
                        </td>
                    </tr>
                    <tr>
                        <td class="inputs">
                            <apex:outputLabel value="Custom Location Name" styleClass="labelCol" />
                        </td>
                        <td class="inputs">
                            <apex:inputField value="{!User.Location_Name__c}" />
                        </td>

                    </tr>
                    <tr>
                        <td class="inputs">
                            <apex:outputLabel value="Units" styleClass="labelCol" />
                        </td>
                        <td class="inputs">
                            <apex:inputField value="{!User.Location_Units__c}" />
                        </td>
                    </tr>

                    <tr>
                        <td class="inputs">
                            <apex:outputLabel value="New Latitude" styleClass="labelCol" />
                        </td>
                        <td class="inputs">
                            <apex:inputField value="{!User.Location_For_Distance_Reporting__Latitude__s}" />
                        </td>
                    </tr>
                    <tr>
                        <td class="inputs">
                            <apex:outputLabel value="New Longitude" styleClass="labelCol" />
                        </td>
                        <td class="inputs">
                            <apex:inputfield value="{!User.Location_For_Distance_Reporting__Longitude__s}" />
                        </td>
                    </tr>
                    <tr>
                        <td></td>
                        <td>
                            <apex:commandButton action="{!saveChanges}" value="Update Values" />

                        </td>

                    </tr>
                </apex:form>
            </table>
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:page>
3
  • I think you are updating the StandardController reference instead of the one you queried for because of a naming conflict. Try renaming getUser to something else and then update your markup to reference the new property.
    – Adrian Larson
    Mar 2, 2016 at 21:21
  • Thanks I changed all references to getUser to getActiveUser but still get the same error.
    – gorav
    Mar 2, 2016 at 21:34
  • Add a pageMessages tag to your markup. Add an error message to the page instead of debugging in your method. Make sure you rerender your pageMessages from your commandButton. You'll probably get better performance though if you validate through javascript.
    – Adrian Larson
    Mar 2, 2016 at 21:56

1 Answer 1

1

Pre-Flight Validation

Visualforce validates all inputs before actually calling your controller (unless you use immediate='true'. The error you're seeing is Visualforce providing automatic validation on your behalf. The only way to circumvent this is to not bind to a field directly, using apex:input or apex:inputText.

Binding to {!User...}

Since you're using the standardController page attribute, getUser won't be called, because that symbol will be bound to the record in StandardController.getRecord that's available from your constructor. If you want to force editing on the current user, either redirect to the page with an ID value for the current user, or don't use a standardController attribute.

Using StandardController

If you are using the standardController attribute, you shouldn't try to update that record using DML operations. Instead, use StandardController.save() to save changes, StandardController.cancel() to abort changes and return to wherever you came from (retURL), or StandardController.view() to abort changes and return to the detail page for the record.

Example

public class UserControllerExtension {
    public User User { get; set; }
    public Integer latitude { get; set; }
    public Integer longitude { get; set; }
    
    public UserControllerExtension() {
        user = [SELECT Id,Location_For_Distance_Reporting__latitude__s, Location_For_Distance_Reporting__longitude__s, Location_Units__c From USER Where Id =:UserInfo.GetuserId()];
        latitude = user.Location_For_Distance_Reporting__latitude__s;
        longitude = user.Location_For_Distance_Reporting__longitude__s;
    }
    
    public void saveChanges() {
        if(Math.abs(longitude) > 180) {
            System.debug('error - longitude out of bounds');
        } else {
            user.Location_For_Distance_Reporting__latitude__s = latitude;
            user.Location_For_Distance_Reporting__longitude__s = longitude;
            update user;
        }
    }
}

Update your page code to remove the standardController, and change the binding values for longitude and latitude to the variables.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .