0
<?php

namespace Drupal\demo\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Component\Serialization\Json;
use Drupal\node\Entity\Node;
use \Drupal\taxonomy\Entity\Term;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\DataCommand;

/**
 * Class Form.
 */
class PurchaseForm extends FormBase
{
    public function getFormId() {
        return 'purchase_form';
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(array $form, FormStateInterface $form_state) {

        $product_type = get_terms_from_vocabulary('product_type', 'All');
        $parks = get_terms_from_vocabulary('theme_parks', 'All');
        $form['#attached']['library'][] = 'demo/demo-ajax-js';
        $form['product_type'] = array (
            '#type' => 'select',
            '#title' => ('Product Type'),
            '#options' => $product_type,
            '#default_value' => $form_state->get('product_type')
        );
        $form['park'] = array (
            '#type' => 'select',
            '#title' => ('Parks'),
            '#options' => $parks,
            '#default_value' => $form_state->get('park')
        );
        $form['date'] = array (
            '#type' => 'date',
            '#title' => t('Date'),
            '#required' => TRUE,
            '#default_value' => $form_state->get('date')
        );
        $form['actions'] = [
            '#type' => 'actions',
        ];
        $form['actions']['submit'] = array(
            '#type' => 'submit',
            '#value' => $this->t('Get Product'),
            '#button_type' => 'primary',
        );
        if ($form_state->has('page') && $form_state->get('page') == 2) {
            return self::formPageTwo($form, $form_state);
        }
        if ($form_state->has('page') && $form_state->get('page') == 3) {
            return self::formPageThree($form, $form_state);
        }
        return $form;
    }

    public function formPageTwo(array $form, FormStateInterface $form_state) {
        $product_type = $form_state->get('product_type');
        $park = $form_state->get('park');
        $date = $form_state->get('date');
        $products = $form_state->get('product');        
        $form['actions']['next'] = [
            '#type' => 'submit',
            '#button_type' => 'primary',
            '#value' => $this->t('Countinue'),
            '#submit' => ['::submitPageTwo'],
            '#validate' => ['::validatePageTwo'],
        ];
        foreach($products as $product) {            
            $product_node = Node::load($product->nid);
            $title = $product_node->get('title')->value;
            $product_id = $product_node->get('field_productid')->value;
            $product_type = $product_node->get('field_product_type')->target_id;
            $term_name = Term::load($product_type)->get('name')->value;
            $price = $product_node->get('field_price')->value;            
            if ($term_name == 'Dated' && empty($price)) {
                $event_id = $product_node->get('field_event_id')->value;
                $date = date_format(date_create($date),"Y-m-d");                
                $performance_response = Json::decode(\Drupal::service('vgs.performance')->get($event_id, $date, $date));
                foreach($performance_response['Answer']['Search']['PerformanceList'] as $item) {
                    $item_date = date_format(date_create($item['DateTimeFrom']),"Y-m-d");                    
                    if ($item_date == $date) {
                        foreach($item['ProductList'] as $product_data) {
                            if ($product_data['ProductId'] == $product_id) {
                                $price = $product_data['DisplayPrice'];
                                if (!empty($price)) {
                                    break;
                                }                                
                            }   
                        }
                        break;
                    }
                }
            }
            $form[$product_id] = ['#type' => 'details', '#title' => $this->t($title), '#open' => TRUE];
            $form[$product_id]['price'] = [
                '#markup' => '<p>Starting from AED '.$price.' <small>including all taxes </small></p>',
            ];
            $form[$product_id]['minus-'. $product_id] = [
                '#type' => 'button',
                '#value' => $this->t('-'),
                '#ajax' => [
                    'callback' => [$this,'subractProduct'],
                    'event' => 'click',
                    'wrapper' => 'quantity-'. $product_id,
                    'progress' => [
                        'type' => 'throbber',
                        'message' => $this->t('Subracting Product'),
                    ],
                ],
            ];
            $form[$product_id]['quantity-'. $product_id] = [
                '#type' => 'number',                
                '#value' => 0,
                '#prefix' => '<div id="quantity-'. strtolower($product_id).'">',
                '#suffix' => '</div>',
                '#disabled' => TRUE
            ];
            $form[$product_id]['plus-'. $product_id] = [
                '#type' => 'button',
                '#value' => $this->t('+'),
                '#ajax' => [
                    'callback' => [$this,'addProduct'],
                    'event' => 'click',
                    'wrapper' => 'quantity-'. $product_id,
                    'progress' => [
                        'type' => 'throbber',
                        'message' => $this->t('Adding Product'),
                    ],
                ],
                '#description' => $product_id 
            ];   
                 
        }      
        return $form;
    }

    public function formPageThree(array &$form, FormStateInterface $form_state) {

    }

    public function validateForm(array &$form, FormStateInterface $form_state) {

    }

    public function submitForm(array &$form, FormStateInterface $form_state) {  
        $product_type = $form_state->getValue('product_type');
        $park = $form_state->getValue('park');
        $date = $form_state->getValue('date');        
        $products = get_product($product_type, $park);
        $form_state->set('product_type', $product_type);
        $form_state->set('park', $park);
        $form_state->set('date', $date);
        $form_state->set('product', $products)
        ->set('page', 2)
        ->setRebuild(TRUE);
    }

    public function subractProduct(array &$form, FormStateInterface $form_state) {
        dpm($form_state);
        $triggering_element = $form_state->getTriggeringElement();
        $element_name = $triggering_element['#id'];
        $pattern = '/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/';
        $product_id = '';
        if (preg_match($pattern, $element_name, $matches)) {
            $product_id = $matches[1];            
        }
        $quantity = $form_state->getValue('quantity-'.strtoupper($product_id));
        if ($quantity > 0) {
            $quantity -= 1;
        }
        $form[$product_id]['quantity-'. $product_id]['widget'][0]['#value'] = $quantity;
        //return $form[$product_id]['quantity-'. $product_id];
        $response = new AjaxResponse();
        $response->addCommand(new InvokeCommand(NULL, 'subCallback', [$product_id]));      
        return $response;
    }

    public function addProduct(array &$form, FormStateInterface $form_state) {
        dpm($form_state);
        $triggering_element = $form_state->getTriggeringElement();
        $element_name = $triggering_element['#id'];
        \Drupal::logger('demo')->notice($element_name);
        $pattern = '/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/';
        $product_id = '';
        if (preg_match($pattern, $element_name, $matches)) {
            $product_id = end($matches);            
        }              
        \Drupal::logger('demo')->notice($product_id);
        //$quantity = $form_state->getValue('quantity-'.strtoupper($product_id));
        //$quantity += 1;
        $response = new AjaxResponse();
        $response->addCommand(new InvokeCommand(NULL, 'addCallback', [$product_id]));      
        return $response;
        //return $form[$product_id]['quantity-'. $product_id];
    }
}

Above code have multistep form which have list of products each products have plus and minus button with ajax call to increase and decrease quantity of product but each time a click plus or minus button it only returns last element in triggering element in ajax callback

1
  • I didn't read the full code as it's not very pleasant to read, but try to give your ajax buttons distinct #name attributes.
    – berliner
    Oct 27, 2023 at 20:14

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.