Drag and drop mediante controles MVC de DevExpress

En estos momentos estoy trabajando en un proyecto utilizando extensiones MVC de DevExpress, y quería añadir la funcionalidad de arrastrar y soltar (drag & drop) dentro de un FormLayout Control en la vista de un listado. Es decir, el usuario podrá agregar/quitar, es decir, arrastrar y soltar para organizar elementos <li>, para después, obtener el orden final actualizado. Dado que la funcionalidad no está integrada en el control DevExpress, decidí modificar la librería open source que estaba usando, jQuery-UI.

En este artículo utilizaré DevExpress, Bootstrap y la librería jQuery-ui.

Descripción de la función

El usuario puede añadir nuevos elementos a la lista mediante el cuadro de texto y el botón "Add", reorganizar los elementos enumerados arrastrando y soltando, quitar un elemento haciendo clic en el botón (x) a la derecha del mismo y durante todos estos eventos, se actualizará la base de datos.

Se deshabilitará el botón “Add” si el cuadro de texto “Name” está vacío. Esto evita que se agreguen elementos vacíos a la lista.

Echa un vistazo:

El código

Para ver el código completo de index.cshtml pincha en este enlace.

Lo primero que tenemos que hacer es crear el FormLayout mediante código Razor. Después añadimos la funcionalidad sortable de jQuery-ui en el elemento <ul>

1. Creamos el control FormLayout en el index.cshtml

// FormLayout control from DevExpress
@Html.DevExpress().FormLayout(formLayoutSettings =>
{
    formLayoutSettings.Name = "mainForm";
    formLayoutSettings.Width = 
        System.Web.UI.WebControls.Unit.Percentage(50); // set the width to 50%

    // Display List Items Group
    formLayoutSettings.Items.AddGroupItem(listItemsSettings =>
    {
        listItemsSettings.Caption = "Display List Items";

        listItemsSettings.Items.Add(i =>
        {
            i.ShowCaption = DefaultBoolean.False;
            i.SetNestedContent(() =>
            {
                // every time new item is added/removed or re-ordered, 
                // this display <p> will get updated
                ViewContext.Writer.Write("<p id='listItems'></p>");
            });
        });
    });

    // Input Group
    formLayoutSettings.Items.AddGroupItem(inputGroupSettings =>
    {
        inputGroupSettings.Caption = "Input";

        inputGroupSettings.Items.Add(i =>
        {
            i.ShowCaption = DefaultBoolean.False;

            i.SetNestedContent(() =>
            {
                // puts some padding for the layout
                ViewContext.Writer.Write("<table><tr><td style="padding-right:5px;">");

                // text box for list item name
                Html.DevExpress().TextBox(tbs =>
                {
                    tbs.Name = "listItemTextBox";
                    tbs.Properties.Caption = "Name";
                    tbs.Properties.ClientSideEvents.KeyUp = 
                      "OnlistItemTextBoxKeyUp"; // checks when to enable/disable Add button
                }).GetHtml();

                ViewContext.Writer.Write("</td><td>");

                Html.DevExpress().Button(bs =>
                {
                    bs.Name = "addButton";
                    bs.Text = "Add";
                    bs.ClientSideEvents.Click = "OnAddButtonClick";
                    bs.ClientEnabled = false; // by default or initial load 
                                              // keeps the button disabled
                }).GetHtml();

                ViewContext.Writer.Write("</td></tr></table>");

                ViewContext.Writer.Write("<br />");

                // List items can be re-arranged, deleted from this <ul> element
                ViewContext.Writer.Write("<h5><strong>List Items:</strong></h5>
                <div style='width:100%; height:150px; overflow:auto; border:solid thin;'>
                <ul id='ulContent'></ul></div>");

            });
        });
    });

}).GetHtml()

2. Después, añadimos CSS para el diseño de las listas

<style>
    #ulContent {
        list-style-type: none; /*removes the default bullet point*/
        margin: 0;
        padding: 0;
    }

    #ulContent li { /* makes the room for adding draggable icon on the left */
        margin: 0 3px 3px 3px;
        display: list-item;
        padding-left: 1.5em;
    }

    #ulContent li span { /* aligns the span properly */
        display: inline-block;
        margin-left: -1.3em;
    }
</style>

3. Ahora, añadimos el Javascript que gestiona el evento drag & drop, modificamos la vista después de cada inserción/eliminación/cambio de orden de la lista de elementos.

$(document).ready(function () {
        $(function () {
            // makes the <li> elements to be draggable by using jQuery-ui library
            $("#ulContent").sortable();
            // disable selection
            $("#ulContent").disableSelection();
        });

        // attach update event for the unordered list element
        // (this event is triggered when new list item is added, 
        // removed or re-arranged by dragging)
        $("#ulContent").sortable({
            update: function (event, ui) {
                // Update the display label
                updateDisplayLabel();
            }
        });
    });

    // when list element element's remove (x) button is clicked, 
    // remove the element from the list and updates the display label
    function OnRemoveListItem(buttonElement) {
        //  get parent element of the button and remove it
        $(buttonElement).parent().remove();

        // Update the display label
        updateDisplayLabel();
    }

    // checks whether to enable/disable the Add button
    function OnlistItemTextBoxKeyUp(s, e) {
        if (s.GetText().trim() == "") {
             // disable the Add button if the text box is empty or contains only spaces
            addButton.SetEnabled(false);
        } else {
            addButton.SetEnabled(true);
        }
    }

    // When Add button is clicked, adds the new list item to the un ordered list element
    function OnAddButtonClick(s, e) {
        $('#ulContent').append("<li class='ui-state-default'>
         <span class='ui-icon ui-icon-arrowthick-2-n-s' style='align-content:center'></span>" + 
         listItemTextBox.GetText() + "<span role='button' onclick='OnRemoveListItem($(this))' 
         class='ui-icon ui-icon-circlesmall-close' style='float:right'></span></li>");

        // resets the textbox to empty string
        listItemTextBox.SetText("");
        // disable the Add button
        addButton.SetEnabled(false);

        // Update the display label
        updateDisplayLabel();
    }

    // updates the display label
    function updateDisplayLabel() {
        var listItemsString = "";
        // loop through all list item inside the ulContent
        $("#ulContent li").each(function (idx, li) {
            listItemsString = listItemsString + " <" + $(li).text() + ">";
        });

        // set the new label for Display List Items
        $("#listItems").text(" " + listItemsString);
    }

Fuente: asutreja

Guardar

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP