【问题标题】:Product autocomplete input on module (Prestashop)模块上的产品自动完成输入(Prestashop)
【发布时间】:2015-06-10 12:00:08
【问题描述】:

我正在开发一个 prestashop 模块,它必须列出现有产品。

对于模块的配置面板,使用 renderForm()getContent(),我正在尝试复制“附件”功能,您可以从这里开始编写输入中产品的一些信息,它显示了匹配的产品。选择该产品时,它会被添加到列表中。像这样:

这是目录/产品/关联选项卡的屏幕截图。

我正在尝试使用 PS 1.6.0.14 和 PS1.6.1.0RC3。我将如何复制此功能以在模块配置面板上获取产品列表?

我试着在这里查看Prestashop AdminProductsController.php,但我真的不明白其中一半的信息来自哪里。

【问题讨论】:

    标签: prestashop prestashop-1.6


    【解决方案1】:

    prestashop 中有一个自动完成插件,您必须为此使用它。它在 js->jquery->plugins 中,您必须将此插件添加到您的模块中以使其工作。

    【讨论】:

    • 但是怎么做呢?大师教我。
    • 教我们老师
    【解决方案2】:

    我认为要实现该功能,renderForm() 函数是不够的,因为您必须绑定一些 javascript 和一些自定义 html。

    编写一个全功能模块的过程有点长,但是以配件功能为起点,它不会那么难,并且您将始终有“如何做”的参考。 我会选择这个:

    1) 首先创建你的

    getContent()

    能够显示自定义模板和与您的模块关联的产品的功能,因此我们将有一些东西:

        public function getContent(){
    
        //post process part to save the associations
        if(Tools::isSubmit('saveMyAssociations'){
         ... //we will see it later
        }
    
        $my_associations = MyModule::getAssociationsLight($this->context->language->id,Tools::getValue('id_product')); //function that will retrieve the array of all the product associated on my module table.
    
         $this->context->smarty->assign(array(
                        'my_associations' => $my_associations,
                        'product_id' => (int)Tools::getValue('id_product')
                    ));
    
        return $this->display(__FILE__, 'views/templates/admin/admintemplate.tpl'); //custome template to create the autocomplete
    
        }
    
    //our little function to get the already saved list, for each product we will retrieve id, name and reference with a join on the product/product_lang tables.
     public static function getAssociationsLight($id_lang, $id_product, Context $context = null)
        {
            if (!$context)
                $context = Context::getContext();
    
            $sql = 'SELECT p.`id_product`, p.`reference`, pl.`name`
                    FROM `'._DB_PREFIX_.'my_associations`
                    LEFT JOIN `'._DB_PREFIX_.'product` p ON (p.`id_product`= `id_product_2`)
                    '.Shop::addSqlAssociation('product', 'p').'
                    LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (
                        p.`id_product` = pl.`id_product`
                        AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').'
                    )
                    WHERE `id_product_1` = '.(int)$id_product;
    
            return Db::getInstance()->executeS($sql);
        }
    

    2) 创建一个能够显示自动完成和列表的模板。 在这里,我们将遍历保存的关联以创建我们的自动完成列表,我们将使用一些隐藏字段来跟踪 ids/name 以及一个可见列表,如果我们将为每一行提供一个删除按钮。

            <input type="hidden" name="inputMyAssociations" id="inputMyAssociations" value="{foreach from=$my_associations item=accessory}{$accessory.id_product}-{/foreach}" />
            <input type="hidden" name="nameMyAssociations" id="nameMyAssociations" value="{foreach from=$my_associations item=accessory}{$accessory.name|escape:'html':'UTF-8'}¤{/foreach}" />
            <div id="ajax_choose_product_association">
                <div class="input-group">
                    <input type="text" id="product_autocomplete_input_association" name="product_autocomplete_input_association" />
                    <span class="input-group-addon"><i class="icon-search"></i></span>
                </div>
            </div>
    
            <div id="divMyAssociations">
                {foreach from=$my_associations item=accessory}
                    <div class="form-control-static">
                        <button type="button" class="btn btn-default delAssociation" name="{$accessory.id_product}">
                            <i class="icon-remove text-danger"></i>
                        </button>
                        {$accessory.name|escape:'html':'UTF-8'}{if !empty($accessory.reference)}{$accessory.reference}{/if}
                    </div>
                {/foreach}
            </div>
        <input type="submit" name="submitMyAssociations" id="submitMyAssociations" value="Send"/>
        <input type="hidden" name="productId" id="productId" value="{$product_id|escape:'html'}"/>
    

    3) 现在我们可以添加 javascript 以在主输入上绑定自动完成功能并执行每个操作的所有逻辑

        $(document).ready(function(){
    //our function wrapper.
                var initMyAssociationsAutocomplete = function (){
    //initialize the autocomplete that will point to the default ajax_products_list page (it returns the products by id+name)
                    $('#product_autocomplete_input_association')
                            .autocomplete('ajax_products_list.php', {
                                minChars: 1,
                                autoFill: true,
                                max:20,
                                matchContains: true,
                                mustMatch:true,
                                scroll:false,
                                cacheLength:0,
                                formatItem: function(item) {
                                    return item[1]+' - '+item[0];
                                }
                            }).result(addAssociation);
        //as an option we will add a function to exclude a product if it's already in the list
                    $('#product_autocomplete_input_association').setOptions({
                        extraParams: {
                            excludeIds : getAssociationsIds()
                        }
                    });
                };
        //function to exclude a product if it exists in the list
                var getAssociationsIds = function()
                {
                    if ($('#inputMyAssociations').val() === undefined)
                        return '';
                    return $('#inputMyAssociations').val().replace(/\-/g,',');
                }
        //function to add a new association, adds it in the hidden input and also as a visible div, with a button to delete the association any time.
                var addAssociation = function(event, data, formatted)
                {
                    if (data == null)
                        return false;
                    var productId = data[1];
                    var productName = data[0];
    
                    var $divAccessories = $('#divCrossSellers');
                    var $inputAccessories = $('#inputMyAssociations');
                    var $nameAccessories = $('#nameMyAssociations');
    
                    /* delete product from select + add product line to the div, input_name, input_ids elements */
                    $divAccessories.html($divAccessories.html() + '<div class="form-control-static"><button type="button" class="delAssociation btn btn-default" name="' + productId + '"><i class="icon-remove text-danger"></i></button>&nbsp;'+ productName +'</div>');
                    $nameAccessories.val($nameAccessories.val() + productName + '¤');
                    $inputAccessories.val($inputAccessories.val() + productId + '-');
                    $('#product_autocomplete_input_association').val('');
                    $('#product_autocomplete_input_association').setOptions({
                        extraParams: {excludeIds : getAssociationsIds()}
                    });
                };
        //the function to delete an associations, delete it from both the hidden inputs and the visible div list.
                var delAssociations = function(id)
                {
                    var div = getE('divMyAssociations');
                    var input = getE('inputMyAssociations');
                    var name = getE('nameMyAssociations');
    
                    // Cut hidden fields in array
                    var inputCut = input.value.split('-');
                    var nameCut = name.value.split('¤');
    
                    if (inputCut.length != nameCut.length)
                        return alert('Bad size');
    
                    // Reset all hidden fields
                    input.value = '';
                    name.value = '';
                    div.innerHTML = '';
                    for (i in inputCut)
                    {
                        // If empty, error, next
                        if (!inputCut[i] || !nameCut[i])
                            continue ;
    
                        // Add to hidden fields no selected products OR add to select field selected product
                        if (inputCut[i] != id)
                        {
                            input.value += inputCut[i] + '-';
                            name.value += nameCut[i] + '¤';
                            div.innerHTML += '<div class="form-control-static"><button type="button" class="delAssociation btn btn-default" name="' + inputCut[i] +'"><i class="icon-remove text-danger"></i></button>&nbsp;' + nameCut[i] + '</div>';
                        }
                        else
                            $('#selectAssociation').append('<option selected="selected" value="' + inputCut[i] + '-' + nameCut[i] + '">' + inputCut[i] + ' - ' + nameCut[i] + '</option>');
                    }
    
                    $('#product_autocomplete_input_association').setOptions({
                        extraParams: {excludeIds : getAssociationsIds()}
                    });
                };
    
        //finally initialize the function we have written above and create all the binds.
                    initMyAssociationsAutocomplete();
    //live delegation of the deletion button to our delete function, this will allow us to delete also any element added after the dom creation with the ajax autocomplete.
                    $('#divMyAssociations').delegate('.delAssociation', 'click', function(){
                        delAssociations($(this).attr('name'));
                    });
             });
    

    4) 现在您只需要保存模块自动完成所建立的关联,我建议先删除在给定产品上建立的任何关联然后保存所有关联来执行它。所以你不必关心插入或更新条目

    public function getContent(){
    
    //post process part
    if(Tools::isSubmit('saveMyAssociations'){
    
           $product_id = (int)Tools::getValue('productId');
    // see the function below, a simple query to delete all the associations on a product
                $this->deleteMyAssociations($product_id);
                if ($associations = Tools::getValue('inputMyAssociations'))
                {
                    $associations_id = array_unique(explode('-', $associations));
                    if (count($associations_id))
                    {
                        array_pop($associations_id);
                       //insert all the association we have made.
                        $this->changeMyAssociations($associations_id, $product_id);
    
                    }
                }
    }
    
    }
    
    protected function deleteMyAssociations($product_id){
    return Db::getInstance()->execute('DELETE FROM `'._DB_PREFIX_.'my_associations` WHERE `id_product_1` = '.(int)$product_id);
    }
    
    protected function changeMyAssociations($associations_id, $product_id){
            foreach ($associations_id as $id_product_2)
                Db::getInstance()->insert('my_associations', array(
                    'id_product_1' => (int)$product_id,
                    'id_product_2' => (int)$id_product_2
                ));
    }
    

    我希望它可以帮助您完成所有这些。

    【讨论】:

    • 抱歉耽搁了,我一直在忙另一个项目,这个项目延误了很多。非常感谢您的冗长回复。在接下来的几天里,我将尝试弄清楚。
    • 您完美的解释唯一缺少的是您在数据库中使用了“我的关联”表,而没有说您必须在“安装”模块时创建该表,如果不存在的话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2023-03-20
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多