简体   繁体   中英

Submit form in Ajax without JQuery

I'm trying to follow this guide to update a form field when the user change another field.

I've correctly setup my FormTypes, but I'm having trouble submitting the form in Ajax without JQuery .

I have 2 select :

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

The blockchain field is supposed to update the dapp field.

If I submit the whole form, it's working :

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));
});

But I'm not supposed to submit the whole form, I'm supposed to submit only the blockchain value

I tried a lot of things, like

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...

or

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...

or

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 ?

I also tried with encodeURIComponent ...

I'm out of ideas... Any ideas ? Thanks !

So I chose to use FormData and remove the dapp field.

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);
});

Here's the FormType

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);
        }
    );

}

In order for this to work, I had to add the blockchain field to my Form's Entity, so that the Request handle the field :

/**
 * 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM