2

I´ve searched around but havent been able to find anything yet. Ive created a field in the Account object called "nivel" which means level. The idea is that every account record can have 3 possible values on this new field called "nivel" (nivel1, nivel2, nivel3). Created the field, added some records with the 3 different options.

After that, I created a VF page that displays 3 lists, each for every level type of account (nivel1, nivel2 and nivel3). I need to be able to save changes on those records If i drag and drop between lists. For example If i drag one record from List1 (displays accounts with value "nivel 1") and drop it on the List3. I should then be able to click on my save button and update that "nivel" field for that specific record. Since I draged it from "nivel1" to nivel". After clicking SAVE it should update that record´s field from "nivel1" to nivel3".

I managed to do it with JS. But I need the save functionally to be called from the Controller class and not using JS on the same VF page.

Heres is the code for the Controller class:

public class TheController {
public List<Account> getNivel1Accounts() {
    List<Account> results = [SELECT Name, Id, NIVEL__c FROM Account WHERE NIVEL__c = 'nivel 1'];
    return results;
}
public List<Account> getNivel2Accounts() {
    List<Account> results = [SELECT Name, Id, NIVEL__c FROM Account WHERE NIVEL__c = 'nivel 2'];
    return results;
}
public List<Account> getNivel3Accounts() {
    List<Account> results = [SELECT Name, Id, NIVEL__c FROM Account WHERE NIVEL__c = 'nivel 3'];
    return results;
} 

And heres the VF page.

<apex:page controller="TheController" sidebar="false" showHeader="false">
<script type="text/javascript">
    var __sfdcSessionId = '{!GETSESSIONID()}';
</script>
<script type='text/javascript' src='//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css'></script>
<script src="../../soap/ajax/37.0/connection.js" type="text/javascript"></script>
<script src="../../soap/ajax/37.0/apex.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js">    
</script>   

<style>   
#Nivel_1, #Nivel_2, #Nivel_3 {
    text-align: center;
    border-radius: 20px;
    border: 5px solid #00FFFF;
    font-size: 12px;
    font-family: "Georgia", Georgia, serif;
    width: 160px;
    min-height: 20px;
    list-style-type: none;
    margin: 0px 0px 20px 10px ;
    padding: 5px 0 0 0;
    float: left;
    margin-right: 10px;
    background-color: #7FFFD4;
}
#Nivel_1 li, #Nivel_2 li, #Nivel_3 li {
    text-align: center;
    border-radius: 20px;
    margin: 0px 5px 20px 5px;
    padding: 5px;
    font-size: 1.2em;
    width: 140px;
    background-color: #7FFFD4;
}

.grab {
    cursor: grab;
}

h3 {
    float: center;
    margin: 0px 30px 0px 25px;
    font-size: 18px ;
    font-weight: bold;
    font-family: Arial, Geneva, Helvetica, sans-serif;
}

h2 {
    font-size: 18px ;
    font-weight: italic;
    font-family: Arial, Geneva, Helvetica, sans-serif;
}

p {
    padding: 30px 0px 0px 0px;
    font-size: 18px;
    margin: 0px 80px 20px 0px;
    text-align: justify;    
}

</style>

<script>
    //funcion para obtener el map[id] de cada registro
    var map = {};
    $( function() {
        $( "#Nivel_1, #Nivel_2, #Nivel_3" ).sortable({
            connectWith: ".connectedSortable",
            receive: function(evt, ui) {
                map[ui.item[0].id] = evt.target.id;
                //console.log(map);
            }
        }).disableSelection();
    } );  

    function Save() {
        var accounts = [];

        for (var key in map){
            var account = new sforce.SObject("Account");
            account.id = key;
            account.Nivel__c = map[key].replace("_", " ");
            accounts.push(account);
        }

        results = sforce.connection.update(accounts);

        for (var i = 0; i < results.length; i++) {
        if (results[i].getBoolean("success")) {
            //Guarda LOG de cada movimiento de Cuenta, aun sin guardar.
              console.log("account with id " + results[i].id + " cuenta actualizada");
            } else {
              console.log("Fallo en actualizar cuenta " + results[i]);
            }
        }
        map = {};
        alert("Se guardaron los cambios de las Cuentas!");
    }

</script>

<apex:pageBlock >
<h3>Cuenta Nivel 1</h3>
<h3>Cuenta Nivel 2</h3>
<h3>Cuenta Nivel 3</h3>
</apex:pageBlock>

    <apex:form >
        <ul id="Nivel_1" class="connectedSortable">
            <apex:repeat value="{!Nivel1Accounts}" var="nivel1">
            <li id="{!nivel1.id}" class="grab">{!nivel1.Name}</li>
            </apex:repeat>
        </ul>

        <ul id="Nivel_2" class="connectedSortable">  
            <apex:repeat value="{!Nivel2Accounts}" var="nivel2">
            <li id="{!nivel2.id}" class="grab">{!nivel2.Name}</li>
            </apex:repeat>
        </ul> 

        <ul id="Nivel_3" class="connectedSortable">
            <apex:repeat value="{!Nivel3Accounts}" var="nivel3">
            <li id="{!nivel3.id}" class="grab">{!nivel3.Name}</li>
            </apex:repeat>
        </ul>
        <u1>
            <p>                
            A su izquierda se muestra un listado de Cuentas segun su "NIVEL". Muestra las cuentas actualmente en sistema y sus niveles.
            </p>
            <h2>
            Para cambiar los niveles de las cuentas, solo arrastre una cuenta al nivel deseado. Cuando finalize presione el botón "Guardar Cuentas".    
            </h2>
        </u1>

        <apex:pageBlock >
            <button type="button" onclick="Save()">Guardar Cuentas</button>
        </apex:pageBlock>
    </apex:form>
</apex:page>

This code works but its viewable to the public and so ive been requested to do the save functionality with the controller class instead.

From what ive been reading this can be done in various form. One of them being actionfunction with sObjects.

But Im having trouble expressing the formula to accumulate the IDs of the records draged to new lists.

Any help would be greatly appreciated

1

jQuery provides a method .sortable("toArray") to get the updated list of elements which you can pass to the Apex Controller. For that, you have to do the following changes.

  1. Create three <apex:inputHidden> elements for each list to get values from javascript and bind the values to Controller.
  2. In VF page Save method, update these input fields with the updated list as comma separated String.
  3. Use apex:actionFunction to call the Save method in the Controller.
  4. In Controller get the Account Ids by splitting the String by comma to get the Account Ids.
  5. Update the Accounts with the new dropdown value.

Here is the updated code:

VF Page:

<apex:page controller="DragnDropController" sidebar="false" showHeader="false">
    <script type='text/javascript' src='//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css'></script>
    <script src="../../soap/ajax/37.0/connection.js" type="text/javascript"></script>
    <script src="../../soap/ajax/37.0/apex.js" type="text/javascript"></script>
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js">    
    </script>   

    <style>   
        #Nivel_1, #Nivel_2, #Nivel_3 {
            text-align: center;
            border-radius: 20px;
            border: 5px solid #00FFFF;
            font-size: 12px;
            font-family: "Georgia", Georgia, serif;
            width: 160px;
            min-height: 20px;
            list-style-type: none;
            margin: 0px 0px 20px 10px ;
            padding: 5px 0 0 0;
            float: left;
            margin-right: 10px;
            background-color: #7FFFD4;
        }
        #Nivel_1 li, #Nivel_2 li, #Nivel_3 li {
            text-align: center;
            border-radius: 20px;
            margin: 0px 5px 20px 5px;
            padding: 5px;
            font-size: 1.2em;
            width: 140px;
            background-color: #7FFFD4;
        }

        .grab {
            cursor: grab;
        }

        h3 {
            float: center;
            margin: 0px 30px 0px 25px;
            font-size: 18px ;
            font-weight: bold;
            font-family: Arial, Geneva, Helvetica, sans-serif;
        }

        h2 {
            font-size: 18px ;
            font-weight: italic;
            font-family: Arial, Geneva, Helvetica, sans-serif;
        }

        p {
            padding: 30px 0px 0px 0px;
            font-size: 18px;
            margin: 0px 80px 20px 0px;
            text-align: justify;    
        }

    </style>

    <script>
    //funcion para obtener el map[id] de cada registro
    var map = {};
    $( function() {
        $( "#Nivel_1, #Nivel_2, #Nivel_3" ).sortable({
            connectWith: ".connectedSortable",
            receive: function(evt, ui) {
                map[ui.item[0].id] = evt.target.id;
                //console.log(map);
            }
        }).disableSelection();
    } );  

    function Save() {
        var newnivel1List = $("#Nivel_1").sortable("toArray");
        $('input[id*=nivel1List]').val(newnivel1List);
        var newnivel2List = $("#Nivel_2").sortable("toArray");
        $('input[id*=nivel2List]').val(newnivel2List);
        var newnivel3List = $("#Nivel_3").sortable("toArray");
        $('input[id*=nivel3List]').val(newnivel3List);
        saveAccounts();
    }

    </script>

    <apex:pageBlock >
        <h3>Cuenta Nivel 1</h3>
        <h3>Cuenta Nivel 2</h3>
        <h3>Cuenta Nivel 3</h3>
    </apex:pageBlock>

    <apex:form id="theform" >
        <ul id="Nivel_1" class="connectedSortable">
            <apex:repeat value="{!Nivel1Accounts}" var="nivel1">
                <li id="{!nivel1.id}" class="grab">{!nivel1.Name}</li>
            </apex:repeat>
        </ul>

        <ul id="Nivel_2" class="connectedSortable">  
            <apex:repeat value="{!Nivel2Accounts}" var="nivel2">
                <li id="{!nivel2.id}" class="grab">{!nivel2.Name}</li>
            </apex:repeat>
        </ul> 

        <ul id="Nivel_3" class="connectedSortable">
            <apex:repeat value="{!Nivel3Accounts}" var="nivel3">
                <li id="{!nivel3.id}" class="grab">{!nivel3.Name}</li>
            </apex:repeat>
        </ul>
        <u1>
            <p>                
                A su izquierda se muestra un listado de Cuentas segun su "NIVEL". Muestra las cuentas actualmente en sistema y sus niveles.
            </p>
            <h2>
                Para cambiar los niveles de las cuentas, solo arrastre una cuenta al nivel deseado. Cuando finalize presione el botón "Guardar Cuentas".    
            </h2>
        </u1>

        <apex:pageBlock >
            <apex:inputHidden id="nivel1List" value="{!nivel1List}"/>
            <apex:inputHidden id="nivel2List" value="{!nivel2List}"/>
            <apex:inputHidden id="nivel3List" value="{!nivel3List}"/>
            <button type="button" onclick="Save();return false;">Guardar Cuentas</button>
        </apex:pageBlock>
        <apex:actionFunction action="{!saveAccounts}" name="saveAccounts" rerender="theform"/>
    </apex:form>
</apex:page>

Controller:

public class DragnDropController {
    public String nivel1List{get;set;}
    public String nivel2List{get;set;}
    public String nivel3List{get;set;}

    public List<Account> getNivel1Accounts() {
        List<Account> results = [SELECT Name, Id, NIVEL__c FROM Account WHERE NIVEL__c = 'nivel 1'];
        return results;
    }
    public List<Account> getNivel2Accounts() {
        List<Account> results = [SELECT Name, Id, NIVEL__c FROM Account WHERE NIVEL__c = 'nivel 2'];
        return results;
    }
    public List<Account> getNivel3Accounts() {
        List<Account> results = [SELECT Name, Id, NIVEL__c FROM Account WHERE NIVEL__c = 'nivel 3'];
        return results;
    } 
    public PageReference saveAccounts() {
        System.debug('nivel1List = '+nivel1List);
        System.debug('nivel2List = '+nivel2List);
        System.debug('nivel3List = '+nivel3List);
        updateAccounts(nivel1List,'nivel 1');
        updateAccounts(nivel2List,'nivel 2');
        updateAccounts(nivel3List,'nivel 3');
        return null;
    }
    public void updateAccounts(String accListString, String accType){
        List<Account> accList = new List<Account>();
        List<String> listOfAccounts = convertStrToList(accListString);
        for(String str:listOfAccounts){
            Account acc = new Account(Id=str);
            acc.NIVEL__c = accType;
            accList.add(acc);
        }
        update(accList);
    }
    public List<String> convertStrToList(String str) {
        List<String> listToReturn = new List<String>();
        if(String.isNotBlank(str)) {
            for(String eachStr : str.split(',')) {
                listToReturn.add(eachStr);
            }
        }
        return listToReturn;
    }    
}
1
  • Worked like a charm! Thank you good sir I was actually going with actionfunction but was having trouble passing the ids onto the controller. The inputhidden worked very well. Thanks again! – Angel Gimenez May 24 '18 at 1:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.