Özel uzantıda girdi olarak dinamik ızgara eklemenin en iyi yolu Adminhtml


15

Kendi ızgarası olan özel bir mağaza bulma aracı uzantısı oluşturdum ve Adminhtml'deki sayfaları düzenledim ve her şey harika çalışıyor. Mağazaların çalışma saatleri için, özellik seçenekleri gibi dinamik bir ızgara uygulamak istiyorum.

resim açıklamasını buraya girin

Şimdi bir çözüm buldum ama daha iyi ya da en azından daha temiz bir yol olmasını umuyorum. Şu ana kadar formdaki alana bir oluşturucu eklemekfieldset

class Redkiwi_Rkstorelocator_Block_Adminhtml_Rkstorelocator_Edit_Tab_General extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _prepareForm()
    {
        $form = new Varien_Data_Form();
        $this->setForm($form);
        $fieldset = $form->addFieldset('rkstorelocator_form', array('legend'=>Mage::helper('rkstorelocator')->__('Store information')));

        [...]

        $officehours_field = $fieldset->addField('office_hours', 'editor', array(
            'name'      => 'office_hours',
            'label'     => Mage::helper('rkstorelocator')->__('Office hours'),
            'required'  => false,
        ));

        $officehours_block = $this->getLayout()
                                ->createBlock('rkstorelocator/adminhtml_rkstorelocator_edit_renderer_officehours')
                                ->setData(array(
                                    'name'      => 'office_hours',
                                    'label'     => Mage::helper('rkstorelocator')->__('Office hours'),
                                    'required'  => false,
                                ));

        $officehours_field->setRenderer($officehours_block);

        [...]
    }
}

Ve oluşturulacak bir blok sınıfı

class Redkiwi_Rkstorelocator_Block_Adminhtml_Rkstorelocator_Edit_Renderer_Officehours
 extends Mage_Adminhtml_Block_Abstract 
 implements Varien_Data_Form_Element_Renderer_Interface 
{

    public function render(Varien_Data_Form_Element_Abstract $element) 
    {
        $required_indicator = $this->getData('required') ? '<span class="required">*</span>' : '' ;

        $html = '
<table id="attribute-options-table" class="dynamic-grid rkstorelocator-officehours" cellspacing="0" cellpadding="0"><tbody>
    <tr>
        <th>Day indicator</th>
        <th>Opening hour</th>
        <th>Closing hour</th>
        <th>
            <button id="add_new_option_button" title="Add Option" type="button" class="scalable add"><span><span><span>Add Option</span></span></span></button>
        </th>
    </tr>
</tbody></table>

<script type="text/javascript">//<![CDATA[

var _form_html_row = \'<tr class="option-row rkstorelocator-officehours-dayrow" id="hour-row-{{id}}"><td><input name="'.$this->getData('name').'[value][option_{{id}}][0]" value="" class="input-text required-option" type="text"></td><td><input name="'.$this->getData('name').'[value][option_{{id}}][2]" value="" class="input-text required-option" type="text"></td><td><input name="'.$this->getData('name').'[value][option_{{id}}][2]" value="" class="input-text required-option" type="text"></td><td class="a-left" id="delete_button_container_option_{{id}}"><input type="hidden" class="delete-flag" name="'.$this->getData('name').'[delete][option_{{id}}]" value=""/><button onclick="$(\\\'hour-row-{{id}}\\\').remove();" title="Delete" type="button" class="scalable delete delete-option"><span><span><span>Delete</span></span></span></button></td></tr>\';

var _rkstorelocator_counter = 0;

$(\'add_new_option_button\').on(\'click\', \'button\', function(){
    $(\'attribute-options-table\').insert(_form_html_row.replace(/\{\{id\}\}/ig, _rkstorelocator_counter));
    _rkstorelocator_counter++;
});

//]]></script>
        ';
        return $html;
    }

}

Bu da bana şu sonucu veriyor resim açıklamasını buraya girin

Şimdi bu temelde çalışıyor ama mevcut değerleri almak oldukça dağınık olacak ve sonuçta yazdığım koddan çok gurur duymuyorum (tahmin edebileceğiniz gibi).

Çeşitli çözümler için Google'a gittim, ancak hepsi genellikle bu yaklaşımı benimser. Bunu yapmanın daha temiz bir yolunu bilen var mı?


Bu özel modül için kullanılan her dosyanın tam kodunu alabilir miyim.
UdayPavan Reddy

Yanıtlar:


11

Tier fiyatlarının istediğim gibi göründüğünü fark etmem uzun zaman aldı. Böylece Magento'nun Tier fiyatlandırmasıyla nasıl yaptıklarına baktıktan sonra aşağıdakileri yaptım. Büyük kod blokları için önceden özür dilerim ama gelecekteki referans için ilginç olabileceğini düşündüm.

Form sınıfımda Redkiwi_Rkstorelocator_Block_Adminhtml_Rkstorelocator_Edit_Tab_General

class Redkiwi_Rkstorelocator_Block_Adminhtml_Rkstorelocator_Edit_Tab_General extends Mage_Adminhtml_Block_Widget_Form
{
    protected function _prepareForm()
    {
        $form = new Varien_Data_Form();
        $this->setForm($form);
        $fieldset = $form->addFieldset('rkstorelocator_form', array('legend'=>Mage::helper('rkstorelocator')->__('Store information')));

        [...]

        $officehours_field = $fieldset->addField('office_hours', 'text', array(
            'name'      => 'office_hours',
            'label'     => Mage::helper('rkstorelocator')->__('Office hours'),
            'required'  => false,
        ));

        $office_hours = $form->getElement('office_hours');

        $office_hours->setRenderer(
            $this->getLayout()->createBlock('rkstorelocator/adminhtml_rkstorelocator_edit_renderer_officehours')
        );


        [...]
    }
}

Şimdi Office saat blok sınıfı için Redkiwi_Rkstorelocator_Block_Adminhtml_Rkstorelocator_Edit_Renderer_Officehours.

class Redkiwi_Rkstorelocator_Block_Adminhtml_Rkstorelocator_Edit_Renderer_Officehours
 extends Mage_Adminhtml_Block_Widget
 implements Varien_Data_Form_Element_Renderer_Interface
{

    /**
     * Initialize block
     */
    public function __construct()
    {
        $this->setTemplate('rkstorelocator/officehours.phtml');
    }

    /**
     * Render HTML
     *
     * @param Varien_Data_Form_Element_Abstract $element
     * @return string
     */
    public function render(Varien_Data_Form_Element_Abstract $element)
    {
        $this->setElement($element);
        return $this->toHtml();
    }

}

Ve şablon .phtml dosyası adminhtml/default/default/template/rkstorelocator/officehours.phtml

<?php 
$_htmlId      = $this->getElement()->getHtmlId();
$_htmlClass   = $this->getElement()->getClass();
$_htmlName    = $this->getElement()->getName();
$_readonly    = $this->getElement()->getReadonly();

$collection = Mage::registry('rkstorelocator_data')
                ->getOpeningHours()
                ->setOrder('sortorder', 'ASC');

$_counter = 0;
?>
<tr>
    <td class="label"><?php echo $this->getElement()->getLabel() ?></td>
    <td colspan="10" class="grid hours">
        <table id="attribute-options-table" class="dynamic-grid rkstorelocator-officehours" cellspacing="0" cellpadding="0"><tbody>
            <tr>
                <th><?php echo $this->__('Day label') ?></th><th><?php echo $this->__('Opening hour') ?></th><th><?php echo $this->__('Closing hour') ?></th><th><?php echo $this->__('Sortorder') ?></th>
                <th><button id="add_new_option_button" title="Add Option" type="button" class="scalable add"><span><span><span><?php echo $this->__('Add Option') ?></span></span></span></button></th>
            </tr>
<?php foreach ($collection as $_item): ?>
<tr class="option-row rkstorelocator-officehours-dayrow" id="hour-row-<?php echo $_counter?>">
    <td><input name="<?php echo $_htmlName; ?>[value][option_<?php echo $_counter ?>][dayindicator]" value="<?php echo $_item->getDayindicator() ?>" class="input-text" type="text"></td>
    <td><input name="<?php echo $_htmlName; ?>[value][option_<?php echo $_counter ?>][openinghour]" value="<?php echo $_item->getOpeninghour() ?>" class="input-text" type="text"></td>
    <td><input name="<?php echo $_htmlName; ?>[value][option_<?php echo $_counter ?>][closinghour]" value="<?php echo $_item->getClosinghour() ?>" class="input-text" type="text"></td>
    <td><input name="<?php echo $_htmlName; ?>[value][option_<?php echo $_counter ?>][sortorder]" value="<?php echo $_item->getSortorder() ?>" class="input-text" type="text"></td>
    <td class="a-left" id="delete_button_container_option_<?php echo $_counter ?>'">
        <input name="<?php echo $_htmlName; ?>[value][option_<?php echo $_counter ?>][id]" value="<?php echo $_item->getId() ?>" type="hidden">
        <input id="delete-row-<?php echo $_counter ?>" type="hidden" class="delete-flag" name="<?php echo $_htmlName; ?>[delete][option_<?php echo $_counter ?>]" value=""/>
        <button onclick="$('hour-row-<?php echo $_counter ?>').style.display='none'; $('delete-row-<?php echo $_counter ?>').setValue(1);" title="Delete" type="button" class="scalable delete delete-option"><span><span><span>Delete</span></span></span></button>
    </td>
</tr>
<?php
        $_counter++;
    endforeach;
?>
</tbody></table>

<script type="text/javascript">//<![CDATA[

var _form_html_row = '<tr class="option-row rkstorelocator-officehours-dayrow" id="hour-row-{{id}}"><td><input name="<?php echo $_htmlName; ?>[value][option_{{id}}][dayindicator]" value="" class="input-text" type="text"></td><td><input name="<?php echo $_htmlName; ?>[value][option_{{id}}][openinghour]" value="" class="input-text" type="text"></td><td><input name="<?php echo $_htmlName; ?>[value][option_{{id}}][closinghour]" value="" class="input-text" type="text"></td><td><input name="<?php echo $_htmlName; ?>[value][option_{{id}}][sortorder]" value="" class="input-text" type="text"></td><td class="a-left" id="delete_button_container_option_{{id}}"><input name="<?php echo $_htmlName; ?>[value][option_{{id}}][id]" value="" type="hidden"><input id="delete-row-{{id}}" type="hidden" class="delete-flag" name="<?php echo $_htmlName; ?>[delete][option_{{id}}]" value=""/><button onclick="$(\'hour-row-{{id}}\').style.display=\'none\'; $(\'delete-row-{{id}}\').setValue(1);" title="Delete" type="button" class="scalable delete delete-option"><span><span><span>Delete</span></span></span></button></td></tr>';

var _rkstorelocator_counter = <?php echo $_counter?>;

$('add_new_option_button').observe('click', function(){
    $('attribute-options-table').insert(_form_html_row.replace(/\{\{id\}\}/ig, _rkstorelocator_counter));
    _rkstorelocator_counter++;
});

//]]></script>
    </td>
</tr>

Ve sonuç: resim açıklamasını buraya girin

Sevgili geleceğin Google çalışanları, Bu Magento 2.x'i okuduğunuz zaman yayınlanacak. Umarım Magento bu tür şeyleri biraz daha kolaylaştırmıştır. :)


Onları DB'de nasıl saklarsınız? Serileştirilmiş dize olarak?
Sergei Guk

Hayır, çalışma saatleri için ikinci bir masam var. Serileştirmekten daha iyi görünüyordu
Sander Mangel

kabul etti, sadece ürünler için aynısını eklemeniz gerekiyor ve yaklaşık 10 isim-değer çifti olacak. Bu nedenle, bunları dizisel dizeler olarak depolamayı veya ürün başına satır başına 1 çift içeren tablolar oluşturmayı düşünün. Yine de gönderi için teşekkürler!
Sergei Guk

Serileştirilmiş verileri kullanmak istemememin nedeni, veritabanındayken onunla hiçbir şey yapamamanızdır. Bu uzantının bir sonraki sürümünde, açılış saatlerine göre konumları aramak istiyorum. Serileştirilmiş verilerle bu mümkün olmazdı. Şimdi kullanabileceğim bir koleksiyon nesnem var. İkinci tablonun neden olduğu ekstra veriler küçük bir değiş tokuş oldu
Sander Mangel

Günümü kurtardım! Bunun için teşekkürler. Sanırım, $ this-> setTemplate ('rkstorelocator / officehours.phtml'); hile oldu. Javascript bit için daha iyi bir yaklaşım olsaydı.
15'te xelber

3

Bazı kodlarımı Magento şablonlarına göre yazıyorum. Belki faydalı olacaktır.
Bazı sekme arayüzü:

<?php
class Ssd_Shower_Block_Adminhtml_Shower_Edit_Tab_Options
    extends Mage_Adminhtml_Block_Template
    implements Mage_Adminhtml_Block_Widget_Tab_Interface
{

    /** set own teplate */
    public function __construct()
    {
        $this->setTemplate('pregnancy/list/options.phtml');
    }

    /** here some implementation of tab interfeys */


    /** options for every row, they will be rendered as dynamic row with inputs */
    public function getOptionValues()
    {
        $period=$this->getData('period');
        $optionsArr = Mage::helper('shower')->getTipList($period);

        $values = array();
        foreach ($optionsArr as $option) {

            $value = array();
            $value['id'] = $option->getId();
            $value['period_id'] = $period->getId();
            $value['tip_content'] = $option->getTip_content();
            $value['sort_order'] = $option->getSort_order();
            $value['update'] = 1;

            $values[] = new Varien_Object($value);
        }

        return $values;
    }

}

?>

Ve hamilelik / list / options.phtml şablonu:

<div class="entity-edit" id="manage-options-panel">
    <div class="entry-edit-head">
        <h4 class="icon-head head-edit-form fieldset-legend">Some title</h4>
    </div>
    <div class="box">
        <div class="hor-scroll">
            <table class="dynamic-grid" cellspacing="0" cellpadding="0" width="100%">
                <tr id="grid_head">
                    <th style="width:90%!important"><?php echo Mage::helper('pregnancy')->__('Checklist Items') ?></th>
                    <th class="w-150"><?php echo Mage::helper('pregnancy')->__('Position') ?></th>
                    <th class="w-150">
                        <button id="add_new_option_button" class="scalable add" style="" onclick="" type="button">
                            <span><?php echo Mage::helper('pregnancy')->__('Add Checklist Item') ?></span>
                        </button>
                    </th>
                </tr>
                <tr id="attribute-options-table">
                </tr>
                <tr class="no-display template" id="row-template">
                    <td><input name="tip[{{id}}][tip_content]"
                               value="{{tip_content}}"
                               class="input-text required-option full"
                               type="text" disabled="disabled"/></td>

                    <td class="a-center"><input class="input-text" type="text" name="tip[{{id}}][sort_order]"
                                                value="{{sort_order}}"/></td>
                    <td class="a-left">
                        <input type="hidden" class="delete-flag" name="tip[{{id}}][delete]" value=""/>
                        <input type="hidden" class="update-flag" name="tip[{{id}}][update]" value="{{update}}"/>
                        <button class="scalable delete delete-option" type="button"><span>Delete</span></button>
                    </td>
                </tr>
            </table>
        </div>
        <input type="hidden" id="option-count-check" value=""/>
    </div>
</div>

<script type="text/javascript">
    //<![CDATA[
    var optionDefaultInputType = 'text';
    //template for dynamic row
    var templateText =
            '<tr class="option-row">' +
                    '<td><input name="tip[{{id}}][tip_content]" value="{{tip_content}}" class="input-text required-option full" type="text"/><\/td>' +
                    '<td><input class="input-text" type="text" name="tip[{{id}}][sort_order]" value="{{sort_order}}"/><\/td>' +
                    '<td class="a-left">' +
                    '<input type="hidden" class="delete-flag" name="tip[{{id}}][delete]" value="" />' +
                    '<input type="hidden" class="update-flag" name="tip[{{id}}][update]" value="{{update}}"/>' +
                    '<button class="scalable delete delete-option" type="button"><span><?=$this->__("Delete")?></span></button>' +
                    '<\/td>' +
                    '<\/tr>';

    var attributeOption = {
        table : $('attribute-options-table'),
        templateSyntax : /(^|.|\r|\n)({{(\w+)}})/,
        templateText : templateText,
        itemCount : 0,
        totalItems : 0,
        //add dynamic row function
        add : function(data) {
            this.template = new Template(this.templateText, this.templateSyntax);
            if (!data.id) {
                data = {};
                data.id = 'option_' + this.itemCount;
            }
            if (!data.intype)
                data.intype = optionDefaultInputType;

            Element.insert(this.table, {before: this.template.evaluate(data)});
            this.bindRemoveButtons();
            this.itemCount++;
            this.totalItems++;
            this.updateItemsCountField();
        },
        //remove dynamic row function
        remove : function(event) {
            if (confirm('<?php echo $this->__("Do you really delete this tip?");?>')) {
                var element = $(Event.findElement(event, 'tr'));
                element.ancestors().each(function(parentItem) {
                    if (parentItem.hasClassName('option-row')) {
                        element = parentItem;
                        throw $break;
                    } else if (parentItem.hasClassName('box')) {
                        throw $break;
                    }
                });

                if (element) {
                    var elementFlags = element.getElementsByClassName('delete-flag');
                    if (elementFlags[0]) {
                        elementFlags[0].value = 1;
                    }

                    element.addClassName('no-display');
                    element.addClassName('template');
                    element.hide();
                    this.totalItems--;
                    this.updateItemsCountField();
                }
            }
        },
        updateItemsCountField: function() {
            if (this.totalItems > 0) {
                $('option-count-check').value = '1';
            } else {
                $('option-count-check').value = '';
            }
        },
        bindRemoveButtons : function() {
            var buttons = $$('.delete-option');
            for (var i = 0; i < buttons.length; i++) {
                if (!$(buttons[i]).binded) {
                    $(buttons[i]).binded = true;
                    Event.observe(buttons[i], 'click', this.remove.bind(this));
                }
            }
        }

    }
    if ($('row-template')) {
        $('row-template').remove();
    }
    attributeOption.bindRemoveButtons();

    if ($('add_new_option_button')) {
        Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption));
    }
    Validation.addAllThese([
        ['required-option', '<?php echo Mage::helper('pregnancy')->__('Failed') ?>', function(v) {
            return !Validation.get('IsEmpty').test(v);
        }]
    ]);
    Validation.addAllThese([
        ['required-options-count', '<?php echo Mage::helper('pregnancy')->__('Options is required') ?>', function(v) {
            return !Validation.get('IsEmpty').test(v);
        }]
    ]);
<?php
    /** pulling data from Ssd_Shower_Block_Adminhtml_Shower_Edit_Tab_Options **/
    if ($options = $this->getOptionValues()) {
        foreach ($options as $_value): ?>
        attributeOption.add(<?php echo $_value->toJson() ?>);
    <?php endforeach; } ?>
    //]]>
</script>

Yanıt için teşekkürler, bunu nasıl çözdüğümün çizgileri boyunca. Orada senin phtml kullanmak istiyorum bazı parçaları :-)
Sander Mangel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.