কাস্টম এক্সটেনশান অ্যাডমিনটিচটিএমএল ইনপুট হিসাবে ডায়নামিক গ্রিড যুক্ত করার সর্বোত্তম উপায়


15

আমি এটির নিজস্ব গ্রিড এবং এডমিনটিচটিএমএল পৃষ্ঠাগুলি সম্পাদনা করে একটি কাস্টম স্টোর লোকেটার এক্সটেনশন তৈরি করেছি এবং সবকিছু দুর্দান্ত কাজ করে। স্টোরগুলির খোলার সময়গুলিতে আমি অ্যাট্রিবিউট বিকল্পগুলির মতো একটি গতিশীল গ্রিড প্রয়োগ করতে চাই।

এখানে চিত্র বর্ণনা লিখুন

এখন আমি একটি সমাধান খুঁজে পেয়েছি তবে আমি আশা করছি এর থেকে ভাল বা কমপক্ষে আরও ভাল উপায় আছে। আমার এখন পর্যন্ত যা আছে তা ফর্মের ক্ষেত্রে একটি রেন্ডারার যুক্ত করছেfieldset

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);

        [...]
    }
}

এবং রেন্ডার করার জন্য একটি ব্লক ক্লাস

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;
    }

}

যা আমাকে নিম্নলিখিত ফলাফল দেয় এখানে চিত্র বর্ণনা লিখুন

এখন এটি মূলত কাজ করে তবে বর্তমান মানগুলি পাওয়া সেখানে যথেষ্ট অগোছালো হবে এবং সব মিলিয়ে আমি যে কোডটি লিখেছি সে সম্পর্কে আমি খুব বেশি গর্বিত নই (যেমন আপনি কল্পনাও করতে পারেন)।

আমি বেশ কয়েকটি সমাধানের জন্য গুগল করেছি তবে সকলেই সাধারণত এই পদ্ধতিটি গ্রহণ করেন। কেউ কি এটি করার একটি ক্লিনার উপায় জানেন?


আমি কি এই কাস্টম মডিউলটির জন্য ব্যবহৃত প্রতিটি ফাইলের পূর্ণ কোড পেতে পারি?
উদয়পাবন রেড্ডি

উত্তর:


10

টায়ারের দামগুলি আমার পছন্দ মতো দেখায় তা বুঝতে আমার দীর্ঘ সময় লেগেছিল। টায়ার প্রাইজিংয়ের সাথে ম্যাজেন্টো এটি কী করে তা খতিয়ে দেখার পরে আমি নীচের কাজগুলি শেষ করেছি। কোডের বিশাল ব্লকের জন্য আগাম দুঃখিত, তবে আমি ভেবেছিলাম এটি ভবিষ্যতের রেফারেন্সের জন্য আকর্ষণীয় হতে পারে।

আমার ফর্ম ক্লাসে 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')
        );


        [...]
    }
}

এখন অফিস ঘন্টা ব্লক ক্লাসের জন্য 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();
    }

}

এবং টেমপ্লেট। Phtml ফাইল 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>

এবং ফলাফল: এখানে চিত্র বর্ণনা লিখুন

প্রিয় ভবিষ্যতের গুগলরা, আপনি এই ম্যাজেন্টো ২.x পড়ার সময় প্রকাশিত হবে। আসুন আশা করি ম্যাজেন্টো এই ধরণের জিনিসগুলি কিছুটা সহজ করে তুলেছে। :)


এগুলি ডিবিতে কীভাবে সংরক্ষণ করবেন? সিরিয়ালযুক্ত স্ট্রিং হিসাবে?
সের্গেই গুক

নাহ, অফিসের সময়ের জন্য আমার কাছে দ্বিতীয় টেবিল রয়েছে। সিরিয়ালাইজেশনের চেয়ে ভাল বলে মনে হচ্ছে
স্যান্ডার ম্যানগেল

সম্মত হয়েছে, কেবলমাত্র পণ্যগুলির জন্য একই যুক্ত করতে হবে এবং প্রায় 10 নাম-মান জুটি থাকবে। সুতরাং এগুলি সিরিয়ালযুক্ত স্ট্রিং হিসাবে সংরক্ষণ করুন বা প্রতি পণ্য প্রতি সারিতে 1 জোড়া দিয়ে টেবিল তৈরি করুন কিনা তা ভাবছেন। যাইহোক পোস্টের জন্য আপনাকে ধন্যবাদ!
সের্গেই গুক

আমি সিরিয়ালযুক্ত ডেটা ব্যবহার করতে চাইনি কারণ হ'ল ডাটাবেসে থাকাকালীন আপনি এটি দিয়ে কিছুই করতে পারবেন না। এই এক্সটেনশনের পরবর্তী সংস্করণে আমি খোলার সময়ের উপর ভিত্তি করে অবস্থানগুলি অনুসন্ধান করতে চাই। সিরিয়ালযুক্ত ডেটা দিয়ে এটি অসম্ভব হবে। এখন আমার কাছে একটি সংগ্রহ অবজেক্ট রয়েছে যা আমি ব্যবহার করতে পারি। দ্বিতীয় টেবিলের কারণে
বাড়ানো

আমার দিন বাঁচা! তার জন্য ধন্যবাদ. আমার ধারণা, $ this-> setTemplate ('rkstorelocator / অফিসhours.phtml'); কৌশল ছিল। জাভাস্ক্রিপ্ট বিট আরও ভাল পদ্ধতির ছিল আশা করি।
xelber

3

আমি Magento টেমপ্লেট উপর ভিত্তি করে লিখিত আমার কোড কিছু দিতে। সম্ভবত এটি দরকারী হবে।
কিছু ট্যাব ইন্টারফেস:

<?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;
    }

}

?>

এবং গর্ভাবস্থা / তালিকা / বিকল্পগুলি। পিএফটিএমএল টেম্পলেট:

<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>

প্রতিক্রিয়াটির জন্য ধন্যবাদ, আমি কীভাবে এটি সমাধান করেছি তা কিছুটা লাইনের পাশাপাশি রয়েছে। আপনার পিএইচটিএমএলের কিছু অংশ যা আমি ব্যবহার করতে চাই :-)
স্যান্ডার ম্যানগেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.