Как я могу редактировать данные таблицы с помощью Symfony?

0

В моем приложении symfony я просматриваю много просмотров в виде таблицы.

Я бы хотел изменить эти данные, щелкнув по ячейкам таблицы, заполнив новые данные и экономя их динамически.

Я изучил jqGrid, DataTable с jEditable, но никто не предлагает простой способ интеграции с jquery.

Я закончил создание своего собственного вида с формой, которая заменяет строку tr при нажатии на строку таблицы, но это супер обычай, и теперь, когда мне нужно использовать одно и то же поведение для другого элемента, я чувствую себя немного обескураженным.

Есть ли наилучшая практика Symfony? Это работа или Угловое или Реагирование? Что мне делать?

Решение моей мечты было бы тем, что будет знать, какое поле объекта редактируется, редактировать его и проверять сущность перед возвратом результата.

Мой пользовательский код:

{% extends ':Template/Backend:backend.html.twig' %}

{% block title_wrapper %}
    <div class="row wrapper border-bottom white-bg page-heading">
        <div class="col-md-12 col-sm-12">
            <h2 class="inline-block">Coûts d'achat</h2>
            <span id="header_buttons" class="pull-right">
                <a href="{{ path('user_supplier_select') }}" class="btn btn-sm btn-white">Ajouter un fournisseur</a>
            </span>
        </div>
    </div>
{% endblock %}

{% block main %}

    <p>Assignez des fournisseurs à vos ingrédients. Vous pourrez ensuite paramétrer le coût d'achat.</p>
    <p>L'unité utilisée pour la quantité minimale d'achat est l'unité que vous utilisez pour gérer votre stock. Essayez d'adopter la même que votre fournisseur.</p>


    {{ form_start(parameter_cost_form, {'attr' : {'id' : 'parameter_cost_form'}}) }}
    {{ form_errors(parameter_cost_form) }}
    {{ form_stylesheet(parameter_cost_form) }}
    {{ form_javascript(parameter_cost_form) }}


    <br>
    <br>
    <div class="table-responsive">
    <table class="DataTable table table-striped table-bordered table-hover" id="editable" >
        <colgroup>
            <col span="3">
            <col span="1" style="min-width: 80px !important">
        </colgroup>
        <thead>
        <tr>
            <th>Ingrédient</th>
            <th>Marque</th>
            <th title="Quantité disponible dans un produit" data-toggle="tooltip" data-placement="top">Packaging</th>
            <th title="Quantité payée qui divisera le prix pour obtenir le coût par unité" data-toggle="tooltip" data-placement="top">Quantité</th>
            <th title="Unité utilisée pour calculer le coût de revient" data-toggle="tooltip" data-placement="top">Unité</th>
            <th title="Montant payé pour la quantité donnée dans l'unité donnée" data-toggle="tooltip" data-placement="top">Montant HT (€)</th>
            <th title="Quantité minimale d'achat en nombre de produits - permet d'arrondir les commandes à la quantité minimale servie par votre fournisseur" data-toggle="tooltip" data-placement="top">Q d'achat minimale</th>
            <th>Fournisseur</th>
            <th title="Référence qui sera indiquée dans les bons de commande" data-toggle="tooltip" data-placement="top">Référence fournisseur</th>
            <th>Actions</th>
        </tr>
        </thead>
        <tbody>
            <tr id="edit_form" style="display: none;" class="child_collection">
                {# Data-repo and data-id are used for updating the unit fields #}
                <td class="name" data-repo="AppBundle:FoodAnalytics\UserIngredient"></td>
                <td class="brand"></td>
                <td class="packaging"></td>
                <td class="quantity">
                    {{ form_widget(parameter_cost_form.quantity) }}
                    {{ form_errors(parameter_cost_form.quantity) }}
                </td>
                <td class="unit-control">
                    {{ form_widget(parameter_cost_form.unit) }}
                    {{ form_errors(parameter_cost_form.unit) }}
                </td>
                <td class="numberObjects">
                    {{ form_widget(parameter_cost_form.numberObjects)  }}
                    {{ form_errors(parameter_cost_form.numberObjects)  }}
                </td>
                <td class="minimumBuyingQuantity">
                    {{form_widget(parameter_cost_form.minimumBuyingQuantity)  }}
                    {{form_errors(parameter_cost_form.minimumBuyingQuantity)  }}
                </td>
                <td class="userSupplier">
                    {{ form_widget(parameter_cost_form.userSupplier)  }}
                    {{ form_errors(parameter_cost_form.userSupplier)  }}
                </td>
                <td class="supplierReference">
                    {{ form_widget(parameter_cost_form.supplierReference)  }}
                    {{ form_errors(parameter_cost_form.supplierReference)  }}
                </td>
                <td class="action buttons">
                    {{ form_widget(parameter_cost_form.submit) }}
                </td>
            </tr>
        {% set i = 0 %}
        {% for ingredient in user_ingredients %}
            {% for uis in ingredient.userIngredientSuppliers %}
                {% set i = i + 1 %}
                <tr id="ingredient_{{ i }}" data-userIngredientId="{{ ingredient.id }}" data-userIngredientSupplierId="{{ uis.id }}" class="table_row">
                    {# Data-repo and data-id are used for updating the unit fields #}
                    <td class="name" data-id="{{ ingredient.id }}">{{ ingredient.getProductName }}</td>
                    <td class="brand">{{ ingredient.getProductBrand }}</td>
                    <td class="packaging">{{ ingredient.getProductPackaging }}</td>
                    <td class="quantity">{{ uis.quantity }}</td>
                    <td class="unit-control" data-value="{{ uis.unit.id }}">{{ uis.unit }}</td>
                    <td class="numberObjects">{{ uis.getLastNumberObjectValue }}</td>
                    <td class="minimumBuyingQuantity">{{ uis.minimumBuyingQuantity }}</td>
                    <td class="userSupplier" data-value="{{ uis.userSupplier.id }}">{{ uis.userSupplier }}</td>
                    <td class="supplierReference">{{ uis.supplierReference }}</td>
                    <td class="action buttons">
                        <a href="{{ path('user_ingredient_supplier_delete', {'userIngredientSupplier' : uis.id }) }}" class="btn btn-xs btn-white fmu_delete_button"><i class="fa fa-times"></i></a>
                        {#<a href="#/" class="btn btn-xs btn-white add"><i class="fa fa-plus"></i></a>#}
                    </td>
                </tr>
            {% else %}
                {% set i = i + 1 %}
                <tr id="ingredient_{{ i }}" data-userIngredientId="{{ ingredient.id }}" data-userIngredientSupplierId="" class="table_row empty">
                    {# Data-repo and data-id are used for updating the unit fields #}
                    <td class="name" data-id="{{ ingredient.id }}">{{ ingredient.getProductName }}</td>
                    <td class="brand">{{ ingredient.getProductBrand }}</td>
                    <td class="packaging">{{ ingredient.getProductPackaging }}</td>
                    <td class="quantity"></td>
                    <td class="unit-control"></td>
                    <td class="numberObjects"></td>
                    <td class="minimumBuyingQuantity"></td>
                    <td class="userSupplier"></td>
                    <td class="supplierReference"></td>
                    <td class="action buttons">
                        <a href="" class="btn btn-xs btn-white fmu_delete_button" style="display: none;"><i class="fa fa-times"></i></a>
                        {#<a href="#/" class="btn btn-xs btn-white add"><i class="fa fa-plus"></i></a>#}
                    </td>
                </tr>
            {% endfor %}
        {% endfor %}
        </tbody>
        <tfoot>
        <tr>
            <th>Ingrédient</th>
            <th>Marque</th>
            <th>Packaging</th>
            <th>Quantité</th>
            <th>Unité</th>
            <th>Montant HT (€)</th>
            <th>Q d'achat minimale</th>
            <th>Fournisseur</th>
            <th>Référence fournisseur</th>
            <th>Actions</th>
        </tr>
        </tfoot>
    </table>
    </div>

    {{ form_end(parameter_cost_form) }}

    {% import ':Model/Macros:_macros.html.twig' as macros %}
    {{ macros.jqueryui_dialog('.fmu_delete_button', "Confirmation", 'Etes-vous sur de vouloir supprimer les informations de ce produit ?', 'Oui, supprimer', 'Non, annuler') }}

    <script>
        $(function(){

            var $editForm = $('#edit_form');
            var $parameterCostForm = $('#parameter_cost_form');

            $('#editable').on('click', 'td:not(:last-child)', function(){
                var $parent = $(this).parent();
                if ($parent.attr('id') == 'edit_form') {
                    return;
                }
                $($editForm.data('previous')).show();
                $editForm.insertAfter($parent);
                $parent.hide();
                $editForm.data('previous', '#' + $parent.attr('id'));
                $parameterCostForm.data('name', $parent.find('.name').eq(0).html());
                $editForm.find('.help-block').remove();
                $editForm.find('.form-control').attr('style', 'position:absolute !importante;');
                $editForm.show();

                $parameterCostForm.attr('action',  '{{ path('parameter_cost') }}/' + $parent.attr('data-userIngredientId') + ($parent.attr('data-userIngredientSupplierId') ? '/' + $parent.attr('data-userIngredientSupplierId') : ''));

                $editForm.find('.name').eq(0).attr('data-id', $parent.find('.name').eq(0).attr('data-id'));
                $editForm.find('.name').eq(0).html($parent.find('.name').eq(0).html());
                $editForm.find('.brand').eq(0).html($parent.find('.brand').eq(0).html());
                $editForm.find('.packaging').eq(0).html($parent.find('.packaging').eq(0).html());
                $editForm.find('.quantity').eq(0).find('.form-control').val($parent.find('.quantity').eq(0).html());
                $editForm.find('.unit-control').eq(0).find('.form-control').val($parent.find('.unit-control').eq(0).attr('data-value'));
                $editForm.find('.numberObjects').eq(0).find('.form-control').val($parent.find('.numberObjects').eq(0).html());
                $editForm.find('.minimumBuyingQuantity').eq(0).find('.form-control').val($parent.find('.minimumBuyingQuantity').eq(0).html());
                $editForm.find('.userSupplier').eq(0).find('.form-control').val($parent.find('.userSupplier').eq(0).attr('data-value'));
                $editForm.find('.supplierReference').eq(0).find('.form-control').val($parent.find('.supplierReference').eq(0).html());
                $editForm.find('.name').eq(0).trigger('initiated');
            });

            {# Data-repo and data-id are used for updating the unit fields #}
            var updateRow = function(){
                $editForm.find('.form-control').each(function(){
                    var $previous = $($editForm.data('previous'));
                    var thisClass = $(this).closest('td').attr('class');
                    var $eq = $previous.find('.' + thisClass).eq(0);
                    $previous.addClass('edited');

                    if (thisClass == 'unit-control' || thisClass == 'userSupplier') {
                        $eq.html($(this).find('option:selected').text());
                        $eq.attr('data-value', $(this).val())
                    } else {
                        $eq.html($(this).val());
                    }
                })
            };

            $editForm.on('change', '.form-control', updateRow);

            $('body').on('click', '#parameter_cost_form button[type="submit"]', function(e){
                e.preventDefault();
                $(this).attr('disabled', 'disabled');

                var formData = new FormData($parameterCostForm[0]);

                console.log($parameterCostForm.attr('action'));
                $editForm.data('sent', $editForm.data('previous'));

                $.ajax({
                    type        : 'post',
                    url         : $parameterCostForm.attr('action'),
                    data        : formData,
                    contentType: false,
                    cache: false,
                    processData: false
                }).done(function(response){
                    response = JSON.parse(response);
                    if ($editForm.data('previous') == $editForm.data('sent')) {
                        $editForm.find('td:nth-child(n+4)').remove();
                        var $substitutes = $(response.view).find('td');
                        $editForm.append($substitutes);
                        updateRow();

                        if (response.success) {

                            var $previous = $($editForm.data('previous'));
                            if ($previous) {
                                $previous.attr('data-userIngredientSupplierId', response.id).removeClass('edited');
                                $parameterCostForm.attr('action', response.action);
                                console.log(response.action);
                                var $action = $previous.find('.action a').eq(0);
                                if ($action.attr('href') == false) {
                                    $action.attr('href', '{{ path('user_ingredient_supplier_delete') }}' + '/' + response.id);
                                    $action.show();
                                }
                            }
                            $.fn.logMessage('success', "L'ingrédient '" + $parameterCostForm.data('name') + "' a été enregistré.");

                        } else {
                            $.fn.logMessage('error', "L'ingrédient '" + $parameterCostForm.data('name') + "' n'a pas pu être enregistré. Vérifiez la validité des données renseignées.");
                            $editForm.find('.form-control').attr('style', 'position: relative !important;');
                        }

                    } else {
                        var $sent = $($editForm.data('sent'));
                        $('#parameter_cost_form button[type="submit"]').removeAttr('disabled');
                        if ($sent) {
                            if (response.success) {
                                $sent.removeClass('edited');
                                $.fn.logMessage('success', "L'ingrédient '" + $sent.find('.name').eq(0).html() + "' a été enregistré.");
                            } else {
                                $.fn.logMessage('error', "L'ingrédient '" + $sent.find('.name').eq(0).html() + "' n'a pas pu être enregistré. Vérifiez la validité des données renseignées.");
                            }
                        }
                    }

                }).fail(function(){
                    $.fn.logMessage('error', "L'ingrédient '" + $parameterCostForm.data('name') + "' n'a pas pu être enregistré. Vérifiez la validité des données renseignées.");
                });

            })
        });

    </script>

    {{ macros.javascript_json_prefill('initiated', '#edit_form .name') }}


    <style rel="stylesheet">
        .unit-control {min-width: 40px;}
        #edit_form td:nth-child(n+4) {
            padding: 0;
            position: relative;
        }
        #edit_form .form-control, #edit_form .btn {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            height: 100%;
            width:100%;
            border: 0;
        }
        .edited {
            background-color: #fffec9 !important;
        }
    </style>

{% endblock %}
  • 1
    Я разработал что-то вроде этого некоторое время назад, так как я не мог найти ничего хорошего для этого. Что я сделал, так это создал отображение полей формы на столбцы с использованием атрибутов dom. затем, используя Jquery, я заменил бы значения для столбцов этими полями, когда была нажата определенная кнопка в строке, а затем отправил бы их с помощью другой кнопки. Таким образом, вы можете фактически использовать то же действие, которое вы использовали для обработки формы в другом месте, и Вы можете использовать форму Symfony.
  • 1
    Я только что прочитал то, что вы уже сделали, чтобы обойти проблему с несколькими строками , визуализировать форму где-то еще и спрятать ее, и каждый раз, когда нажимается кнопка редактирования в каждой строке, заменяйте поля в этой строке. с полями формы.
Теги:
jqgrid

1 ответ

2
Лучший ответ

У меня были те же требования несколько месяцев назад. И я смог успешно интегрировать бесплатный jqGrid с Symfony 2.7.

Для этого я использовал пакет Symfony, называемый пакетом datagrid. Пакет может быть немного сложным в использовании, но как только он понял, он делает вещи очень легкими. Другие плагины, о которых вы говорили, ухудшаются с точки зрения производительности (крах браузера и т.д.) С увеличением количества строк. В то время как вы можете модифицировать ветку для изменения jqGrid, и она будет вести себя так, как вы хотите, чтобы она преодолела ограничения Symfony.

Все, что я беру из пакета datagrid thrace, это массив json который он возвращает. Я смог полностью настроить интерфейс, который включает в себя операции, такие как редактирование данных, добавление новых данных, сохранение изменений и многое другое. Я создал сетки с более чем 30 столбцами, и они работают очень хорошо, так что вы должны ответить на вашу озабоченность по поводу того, что вы имеете огромные взгляды и сможете их редактировать. jqGrid предоставляет все виды проверки данных, которые вы можете предоставить в самом интерфейсе.

Я предлагаю дать jqGrid (пакет) еще один снимок с Symfony. Я могу определенно помочь вам в интеграции jqGrid и Symfony.

  • 0
    только один участник, это не очень обнадеживает ... вы могли использовать свои собственные формы Symfony?
  • 0
    Извините, что вы подразумеваете под формами? Если вам нужно отредактировать / отобразить данные, вы можете просто создать сущность, а Thrace позаботится обо всем остальном.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню