首页 > 解决方案 > Ajax回调不重建表单drupal 8

问题描述

我创建了一个具有两个 ajax 回调的表单,但它们似乎都没有按预期工作,回调后 form_state 没有重建


namespace Drupal\dashboard\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\Entity\User;
use Drupal\commerce_price\Price;
use Drupal\commerce_order\Entity\OrderItem;
use Drupal\commerce_order\Entity\Order;
use Drupal\taxonomy\Entity\Term;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use CommerceGuys\Addressing\AddressFormat\AddressField;
use Drupal\dashboard\DashboardRepository;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 *  UI to update a record.
 *
 * @ingroup scorecards
 */
class AcfDataUpdateForm extends FormBase {

  /**
   * Our database repository service.
   *
   * @var \Drupal\scorecards\ScorecardsRepository
   */
  protected $repository;

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'acf_data_update_form';
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $form = new static($container->get('dashboard.repository'));
    $form->setStringTranslation($container->get('string_translation'));
    $form->setMessenger($container->get('messenger'));
    return $form;
  }

  /**
   * Construct the new form object.
   */
  public function __construct(DashboardRepository $repository) {
    $this->repository = $repository;
  }

  /**
   * Sample UI to update a record.
   */
public function buildForm(array $form, FormStateInterface $form_state, $order_id = NULL) {
$items = $this->repository->get_order_items($order_id);
$mark_pack = 6;
$uid = \Drupal::currentUser()->id();
$config = \Drupal::config('dashboard.settings');  
foreach($items as $item){
 if($item->purchased_entity == 6 || $item->purchased_entity == 7 || $item->purchased_entity == 8){
    $mark_pack = $item->purchased_entity; 
   }    
    
}
$form['#prefix'] = '<div id="package_design_wrapper-container">';
$form['#suffix'] = '</div>';
$form['order_id'] = array(
'#type' => 'hidden',
'#default_value' => $order_id,
);
$form['package'] = array(
 '#type' => 'container',
 '#prefix' => '<div class="message" id="message"></div>',
 '#attributes' => array('id' => 'marketing-package-wrapper'),
);  
$form['package']['marketing_package'] = array(
  '#type' => 'radios',
  '#default_value' => $mark_pack,
  '#options' => array(
    6 => $this
      ->t('Standard <span>'.$this->getPrice(6).'</span>'),
    7 => $this
      ->t('Premium <span>'.$this->getPrice(7).'</span>'),
    8 => $this
      ->t('Premium + <span>'.$this->getPrice(8).'</span>'),  
  ),  
  '#disabled' => true,
);

$form['package']['designation'] = array(
  '#type' => 'textfield',
  '#prefix' => $this->t('<h3>your designation</h3><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry</p>'),
  '#attributes' => array('placeholder' => 'Type Here'),
);

$form['package']['photograph'] = array(
  '#type' => 'managed_file',
  '#upload_location' => 'public://acf_profile_photos',
  '#multiple'        => FALSE,
  '#upload_validators'    => [
    'file_validate_is_image'      => [],
    'file_validate_extensions'    => array('png jpg jpeg'),
    'file_validate_size'          => array(25600000)
        ],
  '#required' => true,
  '#title' => $this->t('<h3>your photograph</h3><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry</p>'),
);

$form['package']['date'] = array(
  '#type' => 'radios',
  '#default_value' => 1,
  '#options' => $this->getDates(),
  '#required' => true,
  '#prefix' => $this->t('<h3>Award Slot</h3><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry</p>'),
  '#ajax' => [
       'wrapper' => 'wrapper-dropdown',
       'callback' => '::getAwardSlots',
       'method' => 'replace',
       'effect' => 'fade',
       'event' => 'change',
       'progress' => [
             'type' => 'throbber',
             'message' => NULL,
          ],
      ],
);

$form['package']['award_slot'] = array(
  '#type' => 'radios',
  '#default_value' => 1,
  '#options' => $form_state->getValue('date') ? $this->getAwardSlotOptions($form_state->getValue('date')) : $this->getAwardSlotOptions('2021-04-21'),
  '#prefix' => '<div id="wrapper-dropdown">',
  '#suffix' => '</div>',
  '#required' => true,
);

$form['package']['bio'] = array(
  '#type' => 'textarea',
  '#prefix' => $this->t('<h3>Individual Bio</h3><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry</p>'),
  '#attributes' => array('placeholder' => 'Type Here'),
);

$form['package']['plaque_type'] = array(
  '#type' => 'radios',
  '#default_value' => 'remote',
  '#options' => array(
    'remote' => $this
      ->t('remote'),
    'event' => $this
      ->t('event'),   
  ),
  '#required' => true,
  '#prefix' => $this->t('<h3>Plaque Type</h3>'),
);

$form['package']['shipping_address'] = array(
 '#type' => 'container',
 '#states' => array(
    'visible' => array(
      ':input[name="plaque_type"]' => array(
        'value' => 'remote',
      ),
    ),
  ),
);
$form['package']['shipping_address']['markup'] = array(
  '#markup' => ' <h3>shipping address</h3><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry</p>',
);

$form['package']['shipping_address']['address'] = array(
    '#type' => 'address',
    '#default_value' => ['country_code' => 'US'],
    '#used_fields' => [
      AddressField::GIVEN_NAME,
      AddressField::FAMILY_NAME,
      AddressField::ORGANIZATION,
      AddressField::ADDRESS_LINE1,
      AddressField::ADDRESS_LINE2,
      AddressField::LOCALITY,
      AddressField::POSTAL_CODE,
    ],
    '#available_countries' => ['US'],
    '#attributes' => array('class' => array('edit-address')),
);

$form['package']['save'] = array(
    '#type' => 'submit',
    '#submit' => ['::submitPackageDetails'],
    '#name' => 'mark-save',
    '#value' => t('Save'),
    '#validate' => ['::validatePackageDetails'],
    '#prefix' => '<div class="row"><div class="col-md-6">',
    '#suffix' => '</div>',
    '#ajax' => [
       'wrapper' => 'package_design_wrapper-container',
       'progress' => [
             'type' => 'throbber',
             'message' => NULL,
          ],
      ],
    );
$form['package']['submit'] = array(
    '#type' => 'submit',
    '#submit' => ['::submitPackageDetails'],
    '#validate' => ['::validatePackageDetails'],
    '#name' => 'mark-submit',
    '#value' => t('Submit'),
    '#prefix' => '<div class="col-md-6">',
    '#suffix' => '</div></div>',
    '#ajax' => [
       'wrapper' => 'package_design_wrapper-container',
       'progress' => [
             'type' => 'throbber',
             'message' => NULL,
          ],
      ],
    );
    
    
$form['terms'] = array(
   '#type' => 'checkbox',
   '#title' => t('I have read the <a href="/terms-of-service">terms & conditions</a> and agree to comply with them. '),
   '#prefix' => '<div class="row mb-3"><div class="col-12 col-sm-12 col-md-12 col-lg-12">',
   '#suffix' => '</div></div>', 


);
     
$form['#theme'] = 'acf_data_update_form';
return $form;   

 }
  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
     echo "<pre>";
     print_r($form_state->getValues()); 
     die;
      
    $old = $this->repository->save_old_data($old_data, $order_id, $user_id);
    $this->messenger()->addMessage($this->t('Saved old data @entry (@count row updated)', [
      '@count' => $old,
      '@entry' => print_r($old_data, TRUE),
    ]));
    if(!empty($old)){ 
    $count = $this->repository->update_nominee($entry, $order_id, $user_id);
    $this->messenger()->addMessage($this->t('Updated entry @entry (@count row updated)', [ 
      '@count' => $count,
      '@entry' => print_r($entry, TRUE),
    ]));
    }
    $form_state->setRedirect('scorecards.scorecard_entry_list');
  }

  public function validatePackageDetails(array &$form, FormStateInterface $form_state){     
   $fields = array('designation','date','award_slot','plaque_type','bio','photograph');   
   $add_fields = array('given_name','family_name','organization','address_line1','locality','postal_code');     
   $valid = true;   
   if($form_state->getValue('plaque_type') == 'remote'){
    $add = $form_state->getValue('address');       
    foreach($add_fields as $field){
     if(empty($add[$field])){
     $form_state->setErrorByName($add[$field], 'Please enter a valid detail');  
      }    
     }
    }             
   foreach($fields as $field){
     if(empty($form_state->getValue($field))){
      $form_state->setErrorByName($field, 'Please enter a valid detail');
        }      
     }        
  
   
   }
   
  public function submitPackageDetails(array &$form, FormStateInterface $form_state){
      $fields = array('designation','date','award_slot','plaque_type','bio','photograph');    
      $add_fields = array('given_name','family_name','organization','address_line1','locality','postal_code'); 
        if($form_state->getValue('plaque_type') == 'remote'){
         $add = $form_state->getValue('address');  
         }
        $data = array();
        $pid = $form_state->getValue('marketing_package');            
       foreach($fields as $field){
        $data[$field] = $form_state->getValue($field);     
         }
    $data['status'] = 0;     
    $triggering_element = $form_state->getTriggeringElement();
    $button_name = $triggering_element['#name'];
    if($button_name == 'mark-submit'){
     $data['status'] = 1;   
     }
    $order_id = $form_state->getValue('order_id');
    $pid = $form_state->getValue('marketing_package'); 
    $entry = $this->repository->saveAcfDetails($order_id,$pid,$data);
    $entry_add = $this->repository->saveShippingDetails($order_id,$add);
    $this->setFilePermanent($form_state->getValue('photograph')); 
    if($entry && $entry_add){
        $form_state->setRebuild(TRUE);
        $this->messenger->addMessage(t('Your data has been saved successfully!'));
        }
      else{
        $this->messenger->addMessage(t('Your data cannot be Saved'));  
         }            
    } 


  function getPrice($id){
   $variation = \Drupal\commerce_product\Entity\ProductVariation::load($id); 
   return str_replace('USD','$',$variation->getPrice());
   }
  
  function setFilePermanent($image_id){
     if(!empty($image_id)) {
      $file = \Drupal\file\Entity\File::load($image_id[0]);
     if (isset($file) and is_object($file)) {
        $file->setPermanent();  // FILE_STATUS_PERMANENT;
        $file->save();
        }  
      
      }
    }  
  function getDates(){
   $config = $this->config('dashboard.settings');     
   $start_date = $config->get('conference_start_date');
   $no_days = $config->get('no_days');
   $dates = array(); 
   for($i = 1; $i <= $no_days; $i++){
      $j = $i-1;  
     $date = strtotime("{$j} day", strtotime($start_date));
     $new_date = date("d-M-Y", $date);
     $dates[date("Y-m-d", $date)] =  'DAY '.$i.'<span>('.$new_date.')</span>'; 
      }
    return $dates;  
      
      }
  
  function getAwardSlots(array &$form, FormStateInterface $form_state){
    $form_state->setValue('date', $form_state->getValue('date'));
    $form_state->setRebuild(TRUE);
    return $form['package']['award_slot'];      
    }
    
  function getAwardSlotOptions($date){
    $terms = \Drupal::entityManager()->getStorage('taxonomy_term')->loadByProperties(array('name' => $date));
    $term = reset($terms); 
    $award_slots = $term->get('field_award_slot');
    $slots = array();
    foreach($award_slots as $award_slot){ 
     $slots[$award_slot->value] = $award_slot->value;
     }
     return $slots;
     }  
  
}

我还为此表单创建了一个模板

                        <div class="row">
                            <div class="col-12 col-sm-12 col-md-9 col-lg-9">
                                <div class="package_border">
                                    <div class="wellcome_back">
                                        <div class="row">
                                            <div class="col-12 col-sm-12 col-md-12 col-lg-12">
                                                
                                                    <h3>Awardee Deliverables</h3>
                                
                                            </div>
                                        </div>
                                    </div>
                                    <div class="package_header">
                                    <div class="row">
                                        <div class="col-12 col-sm-12 col-md-5 col-lg-5">
                                            <div class="package_header_batch">
                                                <img src="/modules/custom/dashboard/images/package.jpg">
                                                <div>
                                                    <h2>Marketing package</h2>
                                                    <p>Lorem Ipsum is simply</p>
                                                </div>
                                            </div>
                                        </div>
                                        {% if form.package.marketing_package %}
                                        <div class="col-12 col-sm-12 col-md-7 col-lg-7">
                                         {{ form.package.marketing_package }}   
                                        </div>
                                        {% endif %}
                                    </div>
                                </div>
                                <div class="designation_content_wrapper">
                                    <div class="designation_content">
                                    {{ form.package|without('marketing_package','plaque_type','shipping_address','submit','save') }}
                                    {% if form.package.plaque_type %}
                                    <h3>plaque</h3>
                                    <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry</p>
                                    <div class="row mb-5">
                                            <div class="col-12 col-sm-12 col-md-6 col-lg-6">
                                                <figure class="plaque_figure">
                                                    {% set images = getPlaqueBadge() %}
                                                    <img src="{{ images.plaque }}" width="100%">
                                                </figure>
                                            </div>
                                            <div class="col-12 col-sm-12 col-md-6 col-lg-6">
                                                <div class="plaque_type_wrapper">
                                                {{ form.package.plaque_type }}
                                                </div>
                                            </div>
                                        </div>
                                        {% endif %}
                                        {% if form.package.shipping_address %}
                                         {{ form.package.shipping_address }}
                                        {% endif %}
                                        {{ form.package.save }}
                                        {{ form.package.submit }}
                                        
                                    </div>
                                </div>
                                </div>
                                {{ form|without('package') }}
                                
                            </div> 
                                 <div class="col-12 col-sm-12 col-md-3 col-lg-3">
                                <aside class="package_aside">
                                    <div class="package_aside_wrapper">
                                        <h5>jump to</h5>
                                        <ul class="package_aside_list">
                                            <li>
                                                <a href="#" class="active">designation</a>
                                            </li>
                                            <li>
                                                <a href="#">photograph</a>
                                            </li>
                                            <li>
                                                <a href="#">award slot</a>
                                            </li>
                                            <li>
                                                <a href="#">individual boi</a>
                                            </li>
                                            <li>
                                                <a href="#">plaque</a>
                                            </li>
                                            <li>
                                                <a href="#">plaque type</a>
                                            </li>
                                            <li>
                                                <a href="#">shipping address</a>
                                            </li>
                                        </ul>
                                    </div>
                                </aside>
                            </div>  
                            
                        </div>
                    

实际发生的是,在执行 ajax 回调之后,form_state 仍然有用户提交的值,这是它不应该提交的。如果有人知道我在这里做错了什么,请提供帮助。

标签: ajaxformsdrupaldrupal-8

解决方案


这有点旧,但也许可以帮助某人:)。

首先 - 你不能$form_state从 ajax 回调中修改 - 所以$form_state->setRebuid()不会有效果。

AJAX 表单文档中所述,您应该只返回一个标记、一个可渲染数组或一个 AjaxCommand。

这里需要做的是修改ajax回调中元素的值,更像这样:

function getAwardSlots(array &$form, FormStateInterface $form_state){
  $date = $form_state->getValue('date')
  $form['package']['award_slot']['#options'] = $this->getAwardSlotOptions($date);

  return $form['package']['award_slot'];      
}

推荐阅读