在没有 JQuery 的 Ajax 中提交表单

Posted

技术标签:

【中文标题】在没有 JQuery 的 Ajax 中提交表单【英文标题】:Submit form in Ajax without JQuery 【发布时间】:2021-12-21 15:59:38 【问题描述】:

我正在尝试按照this 指南在用户更改另一个字段时更新表单字段。

我已经正确设置了我的 FormTypes,但是我在 没有 JQuery 的情况下在 Ajax 中提交表单时遇到了问题。

我有 2 个选择:

const blockchain = document.getElementById('strategy_farming_blockchain');
const dapp = document.getElementById('strategy_farming_dapp');
const csrf = document.getElementById('strategy_farming__token');

blockchain 字段应该更新dapp 字段。

如果我提交整个表单,它就可以工作:

blockchain.addEventListener('change', function () 
    const form = this.closest('form');
    const method = form.method;
    const url = form.action;

    var request = new XMLHttpRequest();
    request.open(method, url, true);
    request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

    request.onload = function () 
        if (this.status >= 200 && this.status < 400) 
            //Success
            const html = new DOMParser().parseFromString(this.response, 'text/html');
            dapp.innerHTML = html.querySelector('#strategy_farming_dapp').innerHTML;
         else 
            //Error from server
            console.log('Server error');
        
    ;

    request.onerror = function () 
        //Connection error
        console.log('Connection error');
    ;

    request.send(new FormData(form));
);

但我不应该提交整个表单,我应该只提交 blockchain

我尝试了很多东西,比如

var formdata = new FormData(form);
formdata.delete(dapp.name);
request.send(formdata);
// It's working for a new entity, but if I'm editing one, it's not updating the dapp field...

var formdata = new FormData();
formdata.append(this.name, this.value);
formdata.append(csrf.name, csrf.value);
request.send(formdata);
// It's working in a NEW action, but not in an EDIT action...

var data = ;
data[this.name] = this.value;
request.send(data);
//or
request.send(JSON.stringify(data));
//If I dump($request->request) in the controller, it seems like there's no data... 
//Or the request isn't parsed correctly, or there's something missing ?

我也试过encodeURIComponent...

我没有想法......有什么想法吗?谢谢!

【问题讨论】:

请参阅 here 关于 CSRF 令牌。 @Barmar 谢谢。我修复了“CSRF 令牌无效”错误。如果我在一个 NEW 操作中它正在工作,但如果它是一个 EDIT 操作,它不会更新 dapp 字段(我检查了响应并且没有 dapp 字段的新选项......)。我会编辑帖子,但它没有关闭... 如果你只发送blockchain erlement,它怎么知道应该是什么动作? 我也尝试发送整个表单并仅删除带有formdata.delete(dapp.name); 的 dapp 字段,它是一样的 我不知道dapp 是什么,或者你为什么需要删除它。 【参考方案1】:

所以我选择使用FormData 并删除dapp 字段。

const blockchain = document.getElementById('strategy_farming_blockchain');
const dapp = document.getElementById('strategy_farming_dapp');

blockchain.addEventListener('change', function () 
    const form = this.closest('form');
    const method = form.method;
    const url = form.action;

    var request = new XMLHttpRequest();
    request.withCredentials = true;
    request.open(method, url, true);
    request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

    request.onload = function () 
        if (this.status >= 200 && this.status < 400) 
            //Success
            const html = new DOMParser().parseFromString(this.response, 'text/html');
            dapp.innerHTML = html.querySelector('#strategy_farming_dapp').innerHTML;
         else 
            //Error from server
            console.log('Server error');
        
    ;

    request.onerror = function () 
        //Connection error
        console.log('Connection error');
    ;
    var formdata = new FormData(form);
    formdata.set(dapp.name, "");
    request.send(formdata);
);

这是表单类型

public function buildForm(FormBuilderInterface $builder, array $options): void

    $builder
        //...
        ->add('blockchain', EntityType::class, [
            'required' => false,
            'class' => Blockchain::class,
            'attr' => ['class' => 'js-select2'],
        ]);

    $formModifier = function (FormInterface $form, Blockchain $blockchain = null) 
        $dapps = null === $blockchain ? [] : $blockchain->getDapps();
        $form->add('dapp', EntityType::class, [
            'class' => Dapp::class,
            'required' => true,
            'choices' => $dapps,
            'placeholder' => 'My placeholder',
            'attr' => ['class' => 'js-select2'],
        ]);
    ;

    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (FormEvent $event) use ($formModifier) 
            /**
             * @var StrategyFarming $data
             */
            $data = $event->getData();
            $blockchain = $data->getDapp() ? $data->getDapp()->getBlockchain() : null;
            $formModifier($event->getForm(), $blockchain);
        
    );

    $builder->get('blockchain')->addEventListener(
        FormEvents::POST_SUBMIT,
        function (FormEvent $event) use ($formModifier) 
            $blockchain = $event->getForm()->getData();
            $formModifier($event->getForm()->getParent(), $blockchain);
        
    );


为了让它工作,我必须将区块链字段添加到我的表单实体中,以便请求处理该字段:

/**
 * Not persisted
 * @var Blockchain
 */
private $blockchain;

public function getBlockchain(): ?Blockchain

    if ($this->blockchain === null && $this->dapp !== null && $this->dapp->getBlockchain() !== $this->blockchain) 
        $this->blockchain = $this->dapp->getBlockchain();
    
    return $this->blockchain;


public function setBlockchain(?Blockchain $blockchain): self

    $this->blockchain = $blockchain;

    return $this;

【讨论】:

以上是关于在没有 JQuery 的 Ajax 中提交表单的主要内容,如果未能解决你的问题,请参考以下文章

如何使用没有 jQuery 但纯 Javascript 的 AJAX 提交此表单

AJAX、jQuery、Javascript、表单提交和 setTimout() 问题

jQuery 表单验证和 Ajax 提交的问题

jquery AJAX将数据放在表单

如何在 cakephp 中通过 ajax 提交 jquery 移动弹出表单

使用JQuery的ajax提交表单能否使用一个变量来获取form的id