php - español - magento download
¿Cómo permitir la selección de múltiples productos en la configuración del widget de Magento? (5)
Estoy tratando de implementar un widget incrustado. Los administradores podrán configurar este widget e incrustarlo dentro del editor WYSIWYG. Dos de las muchas opciones de configuración son una lista de productos que deberían aparecer en la interfaz y en la lista de categorías.
Quiero permitir esta selección con " adminhtml / catalog_product_widget_chooser " y " adminhtml / catalog_category_widget_chooser ". Traté de implementar estos widgets con escasa documentación disponible en la web, pero lo único que logré es implementar para seleccionar un producto o seleccionar una categoría. Necesito comportamiento de selección múltiple.
Hasta donde puedo ver, la implementación actual no permite ninguna posibilidad de multiselección. Comprobé el código de ambas clases y la plantilla grid.phtml y parece que está mal escrita y no es extensible más allá de la intención de uso actual. Por ejemplo, así es como se supone que debe inicializar el bloque auxiliar para un parámetro de widget para permitir la selección múltiple:
<helper_block>
<type>adminhtml/catalog_product_widget_chooser</type>
<data>
<button translate="open">
<open>Select Products...</open>
</button>
<use_massaction>1</use_massaction>
</data>
</helper_block>
Pero el selector de producto está codificado para su uso sin acciones masivas con esta parte del código:
public function prepareElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$uniqId = Mage::helper(''core'')->uniqHash($element->getId());
$sourceUrl = $this->getUrl(''*/catalog_product_widget/chooser'', array(
''uniq_id'' => $uniqId,
''use_massaction'' => false,
));
...
Y la plantilla grid.phtml que se supone que tiene algún tipo de botón para confirmar la selección múltiple solo muestra los botones "Buscar" y "Restablecer filtro". Y no se maneja agregar otro botón. Por ejemplo, aquí está el código predeterminado responsable de imprimir el botón html:
public function getMainButtonsHtml()
{
$html = '''';
if($this->getFilterVisibility()){
$html.= $this->getResetFilterButtonHtml();
$html.= $this->getSearchButtonHtml();
}
return $html;
}
Solo estos dos botones se imprimirán de forma predeterminada.
Así que comencé mi propia implementación basada en dos implementaciones mencionadas anteriormente y se está volviendo feo y podría terminar como un desastre inmanejable de copy-pasta. Y trabajo por principio que si las cosas empiezan a parecer feas, entonces estoy haciendo algo mal.
Entonces, ¿hay una forma sencilla de implementar productos múltiples y selección de categorías múltiples en la pantalla de configuración de widgets utilizando el widget de cuadrícula?
Aquí hay una solución rápida: no use el selector de artilugios del producto, pero use un campo de texto que permita códigos de artículo separados por comas.
Luego en tu código explota el skus y obtén los productos por sku. Devuélvelo a tu plantilla. Más fácil :)
Encontré una manera rápida de obtener categorías múltiples en los parámetros de widgets usando un modelo fuente basado en adminhtml/system_config_source_category
. Eliminé el filtro de nivel de raíz y agregué una sangría para las subcategorías.
widget.xml:
<widgets>
<my_widget type="mymodule/block" translate="name" module="mymodule">
<name>Widget with Multiselect Categories</name>
<parameters>
<category_ids translate="label description">
<visible>1</visible>
<required>1</required>
<label>Categories</label>
<type>multiselect</type>
<source_model>mymodule/system_config_source_category</source_model>
</category_ids>
</parameters>
</my_widget>
</widgets>
El modelo de origen:
class Mynamespace_Mymodule_Model_System_Config_Source_Category
{
public function toOptionArray()
{
$collection = Mage::getResourceModel(''catalog/category_collection'');
$collection->addAttributeToSelect(''name'')
->addFieldToFilter(''path'', array(''neq'' => ''1''))
->load();
$options = array();
foreach ($collection as $category) {
$depth = count(explode(''/'', $category->getPath())) - 2;
$indent = str_repeat(''-'', max($depth * 2, 0));
$options[] = array(
''label'' => $indent . $category->getName(),
''value'' => $category->getId()
);
}
return $options;
}
}
El resultado:
Fuente: http://www.magentocommerce.com/knowledge-base/entry/tutorial-creating-a-magento-widget-part-2
He agregado una respuesta a esta pregunta. Implementar el widget de selección de productos múltiples Magento
Revisé el Módulo que se encuentra en https://github.com/dio5/magento-multiproducts-widget .
Use la opción FORK en lugar de Download ZIP.
Funciona y nos da los resultados exactos, es decir, selección de productos múltiples en WIDGET. Si hay algún error, házmelo saber.
Avísame si eso funciona para ti.
¡Gracias!
[Editar mi comentario anterior, a pedido del código aquí directamente]
/Namespace/Modulename/etc/widget.xml
<widgets>
<catalog_product_multiproducts type="namespace_modulename/widget_catalog_product_multiproducts" translate="name description" module="namespace_modulename">
<name>Catalog Multiple Products Widget</name>
<description>Select multiple products for display</description>
<parameters>
<title translate="label">
<visible>1</visible>
<label>Title</label>
<type>text</type>
</title>
<products_count translate="label">
<visible>1</visible>
<required>1</required>
<label>No of Products</label>
<type>text</type>
</products_count>
<ids translate="label">
<visible>1</visible>
<required>1</required>
<label>Products</label>
<type>label</type>
<helper_block>
<type>namespace_modulename/adminhtml_catalog_product_widget_multiproducts_chooser</type>
<data>
<button translate="open">
<open>Select Products...</open>
</button>
</data>
</helper_block>
<sort_order>10</sort_order>
</ids>
<template translate="label description">
<required>1</required>
<visible>1</visible>
<label>Product Carousel Template</label>
<type>text</type>
<value>catalog/product/widget/products_carousel.phtml</value>
<values>
<default translate="label"> <value>catalog/product/widget/products_carousel.phtml</value>
<label>New Products Grid Template</label>
</default>
<list translate="label">
<value>catalog/product/widget/new/content/new_list.phtml</value>
<label>New Products List Template</label>
</list>
</values>
<description>Template path cannot be changed/updated</description>
</template>
</parameters>
</catalog_product_multiproducts>
</widgets>
/NameSpace/ModuleName/Block/Adminhtml/Catalog/Product/MultiProducts/Chooser.php
Esta función llamará a la función DOCHOOSE () que ayudará a "Elegir" los productos marcados / seleccionados.
/**
* prepare layout for products grid
*
* @return type Mage_Adminhtml_Block_Catalog_Product_Widget_Chooser
*/
protected function _prepareLayout()
{
$this->setChild(''choose_button'', $this->getLayout()->createBlock(''adminhtml/widget_button'')
->setData(array(
''label'' => Mage::helper(''adminhtml'')->__(''Choose Selected Products''),
''onclick'' => $this->getJsObjectName() . ''.doChoose()''
))
);
return parent::_prepareLayout();
}
La función siguiente se debe usar para preparar el HTML del elemento del producto, en el formato {1} {2}
/**
* Prepare chooser element HTML
*
* @param Varien_Data_Form_Element_Abstract $element Form Element
* @return Varien_Data_Form_Element_Abstract
*/
public function prepareElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$uniqueId = Mage::helper(''core'')->uniqHash($element->getId());
$sourceUrl = $this->getUrl(''*/multiproducts/chooser'', array(
''uniq_id'' => $uniqueId,
''use_massaction'' => true,
));
$chooser = $this->getLayout()->createBlock(''widget/adminhtml_widget_chooser'')
->setElement($element)
->setTranslationHelper($this->getTranslationHelper())
->setConfig($this->getConfig())
->setFieldsetId($this->getFieldsetId())
->setSourceUrl($sourceUrl)
->setUniqId($uniqueId);
if ($element->getValue())
{
$label = "";
$ids = explode(''}{'', $element->getValue());
$cleanIds = array();
foreach ($ids as $id)
{
$id = str_replace(''{'', '''', $id);
$id = str_replace(''}'', '''', $id);
$cleanIds[] = $id;
}
$products = $this->_getProductsByIDs($cleanIds);
if ($products)
{
$label .= ''<ul>'';
foreach ($products as $product)
{
$label .= ''<li>'' . $product->getName() . ''</li>'';
}
$label .= ''</ul>'';
$chooser->setLabel($label);
}
}
$element->setData(''after_element_html'', $chooser->toHtml());
return $element;
}
JS para casilla marcada / no marcada
/**
* Checkbox Check JS Callback
*
* @return string
*/
public function getCheckboxCheckCallback()
{
if ($this->getUseMassaction())
{
return "function (grid, element) {
$(grid.containerId).fire(''product:changed'', {element: element});
}";
}
}
JS para Fila / Producto seleccionado / Controlado / Seleccionado
/**
* Grid Row JS Callback
*
* @return string
*/
public function getRowClickCallback()
{
if (!$this->getUseMassaction())
{
$chooserJsObject = $this->getId();
return ''
function (grid, event) {
var trElement = Event.findElement(event, "tr");
var productId = trElement.down("td").innerHTML;
var productName = trElement.down("td").next().next().innerHTML;
var optionLabel = productName;
var optionValue = "product/" + productId.replace(/^/s+|/s+$/g,"");
if (grid.categoryId) {
optionValue += "/" + grid.categoryId;
}
if (grid.categoryName) {
optionLabel = grid.categoryName + " / " + optionLabel;
}
'' . $chooserJsObject . ''.setElementValue(optionValue);
'' . $chooserJsObject . ''.setElementLabel(optionLabel);
'' . $chooserJsObject . ''.close();
}
'';
}
}
Código JS, si el usuario está interesado en seleccionar productos de una categoría específica.
/**
* Category Tree node onClick listener js function
*
* @return string
*/
public function getCategoryClickListenerJs()
{
$js = ''
function (node, e) {
{jsObject}.addVarToUrl("category_id", node.attributes.id);
{jsObject}.reload({jsObject}.url);
{jsObject}.categoryId = node.attributes.id != "none" ? node.attributes.id : false;
{jsObject}.categoryName = node.attributes.id != "none" ? node.text : false;
}
'';
$js = str_replace(''{jsObject}'', $this->getJsObjectName(), $js);
return $js;
}
JS adicional para preparar el elemento POST con identificadores de productos.
/**
* return additional JS for controls
*
* @return JS
*/
public function getAdditionalJavascript()
{
$chooserJsObject = $this->getId();
$js = ''
{jsObject}.initChecked = function() {
$$("#'' . $chooserJsObject . ''_table tbody input:checkbox").each(function(element, i) {
var values = '' . $chooserJsObject . ''.getElementValue();
var capture = values.replace("{"+element.value+"}", "match");
var searchValue = "match";
if(capture.search(searchValue) != -1)
{
element.checked = true;
}
});
}
{jsObject}.initChecked();
var values = '' . $chooserJsObject . ''.getElementValue();
$("'' . $chooserJsObject . ''").insert({bottom: "<div class=/"filter/"><input type=/"hidden/" value=/"+values+/" name=/"selected_products/" /></div>"});
$$("#'' . $chooserJsObject . ''_table tbody input:checkbox").invoke("observe", "change", function(event) {
var element = Event.element(event);
var label = element.up("td").next().next().next().innerHTML;
label = label.replace(/^/s/s*/, "").replace(//s/s*$/, "");
if(element.checked)
{
{jsObject}.addValue(element.value);
{jsObject}.addLabel(label);
} else {
{jsObject}.removeValue(element.value);
{jsObject}.removeLabel(label);
}
});
{jsObject}.removeValue = function(value) {
var currentValue = '' . $chooserJsObject . ''.getElementValue();
currentValue = currentValue.replace("{"+value+"}", "");
'' . $chooserJsObject . ''.setElementValue(currentValue);
}
{jsObject}.addValue = function(value) {
var currentValue = '' . $chooserJsObject . ''.getElementValue();
currentValue = currentValue.replace("{"+value+"}", "");
currentValue = currentValue + "{"+value+"}";
'' . $chooserJsObject . ''.setElementValue(currentValue);
}
{jsObject}.removeLabel = function(label) {
var currentLabel = '' . $chooserJsObject . ''.getElementLabelText();
currentLabel = currentLabel.replace("<li>"+label+"</li>", "");
'' . $chooserJsObject . ''.setElementLabel(currentLabel);
}
{jsObject}.addLabel = function(label) {
var currentLabel = '' . $chooserJsObject . ''.getElementLabelText();
if(currentLabel.search("ul") != -1)
{
currentLabel = currentLabel.replace("</ul>", "");
currentLabel = currentLabel.replace("<li>"+label+"</li>", "");
} else {
currentLabel = "<ul>";
}
currentLabel = currentLabel +"<li>"+label+"</li></ul>";
'' . $chooserJsObject . ''.setElementLabel(currentLabel);
}
{jsObject}.doChoose = function(node,e) {
'' . $chooserJsObject . ''.close();
}
'';
$js = str_replace(''{jsObject}'', $this->getJsObjectName(), $js);
return $js;
}
Las anteriores funciones principales le ayudarán a seleccionar múltiples productos de la GRID dentro de una ventana emergente.
Hay un poco más sobre el código que puede verificarse aquí: https://github.com/dio5/magento-multiproducts-widget
Pasos:
- Navegue a una página CMS en el panel ADMIN.
- Haga clic en "Insertar Widget" en el editor WYSIWYG
- Seleccionar tipo de widget - Widget de múltiples productos de catálogo
- Introduzca el título, el recuento de productos
- Elija una plantilla (uno puede agregar tantas plantillas como sea necesario como una opción)
- Haga clic en el botón "Seleccionar productos"
- Seleccione productos de la GRID
- Haga clic en el botón "Elegir productos seleccionados"
¡Espero que esto ayude a alguien!
Feliz codificación ...
Intenta con https://github.com/dio5/magento-multiproducts-widget .
Parece muy útil.
Parece que no eres el primero en ir por el camino de desarrollar tu propia implementación para esto.
David Manners parece haber abordado el mismo problema, con sus Manners_Widgets .
Características de la extensión Manners_Widgets:
- Selección múltiple para productos y categorías
No he tenido contacto con David, ni he utilizado esta solución, por lo que no puedo comentar sobre la calidad (o integridad) de este código ... pero si aún no ha visto esta solución, podría ahorrarle algo de tiempo. (o en el peor, darte un punto de contacto para colaborar en este tema).
Espero que esto te ayude, ¡buena suerte con eso!