Symfony2:通过AJAX手动提交没有课程的表单

时间:2016-03-07 12:41:22

标签: javascript php angularjs forms symfony

我们有一个旧网站,我已经实现了一个由AngularJS发送到PHP脚本的表单,并在处理完电子邮件后发送。如果表单无效,PHP脚本将返回带有验证错误的JSON。由于我们已经将Symfony用于其他一些应用程序(REST API),我认为在Symfony中重新实现我的普通PHP脚本会很好。

为了简单起见,我只放了一小段相关的代码片段。这就是我所拥有的:

HTML(ng-app绑定在body标签上,此处未显示):

<form name="infoscreenForm" class="form-horizontal" enctype="multipart/form-data" ng-controller="FormController">
    <div class="form-group">
        <div class="col-lg-1 control-label">*</div>
        <div class="col-lg-11 input-group">
            <input type="text" class="form-control" id="contact_person"
                   name="contact_person" ng-model="formData.contactPerson"
                   placeholder="Kontaktperson">
        </div>
        <span class="text-warning" ng-show="errors.contactPerson">
            {{ errors.contactPerson }}
        </span>
    </div>
    <div class="form-group">
        <div class="col-lg-1 control-label">*</div>
        <div class="col-lg-11 input-group">
            <span class="input-group-addon">@</span>
            <input type="email" class="form-control" id="email" name="email"
                   ng-model="formData.email" placeholder="E-Mail">
        </div>
        <span class="text-warning" ng-show="errors.email">
            {{ errors.email }}
        </span>
    </div>
    <div class="form-group">
        <div class="col-lg-1 control-label">&nbsp;</div>
        <div class="col-lg-11 input-group">
            <input type="file" class="form-control" id="file" name="file"
                   file-model="formData.file"
                   accept="application/pdf,image/jpeg,image/png">
        </div>
        <span class="text-warning" ng-show="errors.file">
            {{ errors.file }}
        </span>
    </div>
    <div class="form-group">
        <button type="submit" class="btn btn-default" id="submit"
                name="submit" ng-click="submitForm()">
            Formular absenden
        </button>
    </div>
</form>

JS:

var app = angular.module('InfoscreenApp', []);

app.directive('fileModel', ['$parse', function ($parse) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      var model = $parse(attrs.fileModel);
      var modelSetter = model.assign;

      element.bind('change', function () {
        scope.$apply(function () {
          modelSetter(scope, element[0].files[0]);
        });
      });
    }
  };
}]);

app.factory('multipartForm', ['$http', function ($http) {
    return {
      post : function (uploadUrl, data) {
        var fd = new FormData();
        for (var key in data) {
          fd.append(key, data[key]);
        }
        return $http.post(uploadUrl, fd, {
            transformRequest: angular.identity,
            headers : { 'Content-Type': undefined }

        });
      }
    };
}]);

app.controller('FormController', ['$scope', 'multipartForm', function ($scope, multipartForm) {
    $scope.formData = {};

    $scope.submitForm = function () {
      var uploadUrl = 'http://localhost:8000/infoscreen';
      multipartForm.post(uploadUrl, $scope.formData)
      .then(function (data) {
        console.log(data);

        if (data.success) {
          $scope.message = data.data.message;
          console.log(data.data.message);
        } else {
          $scope.errors = data.data.errors;
        }
      });
    };
}]);

使用普通的PHP脚本一切正常。这是我在Symfony中尝试做的事情:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\Email;

class DefaultController extends Controller
{
    /**
     * @Route("/infoscreen", name="infoscreen")
     */
    public function infoscreenAction(Request $request)
    {
        $defaultData = array('message' => 'infoscreenForm');
        $form = $this->createFormBuilder($defaultData)
            ->add('contactPerson', TextType::class, array(
                'constraints' => array(
                    new NotBlank(),
                )
            ))
            ->add('email', EmailType::class, array(
                'constraints' => array(
                    new NotBlank(),
                    new Email(),
                )
            ))
            ->add('file', FileType::class)
            ->add('submit', SubmitType::class)
            ->getForm();
        ;

        $form->submit($request->request->get($form->getName()));
        $data = $form->getData();

        if ($form->isValid()) {
            echo 'Alles ok';
            // send an email
        }

        $errors = array();
        $validation = $this->get('validator')->validate($form);
        foreach ($validation as $error) {
            $errors[$error->getPropertyPath()] = $error->getMessage();
        }

        $response = new Response();
        $response->setContent(json_encode(array(
            'form_data' => $data,
            'errors' => $errors,
        )));
        $response->headers->set('Content-Type', 'application/json');

        return $response;
    }
}

config.yml中禁用了CSRF。表单未绑定到实体类。提交表单后,我在控制台中获得以下对象:

{
    data: Object,
    status: 200,
    config: Object,
    statusText: "OK"
}

重要的部分在data: Object

{
    form_data: {
        contactPerson: null,
        email: null,
        message: "infoscreenForm",
        file: null
    },
    errors : {
        children[contactPerson].data = "This value should not be blank",
        children[email].data = "This value should not be blank"
    }
}

当我提交表单并在字段中输入一些值时会发生这种情况。似乎提交的数据未绑定到控制器中的表单。我可能遗漏了一些东西,但我卡在这里,不知道如何继续。我尝试使用$form->bind($request)$form->handleRequest($request)和其他一些东西,但它没有用。即使我单独绑定字段,我仍然不会在表单中获取它们的值。

请有人帮助我。

提前致谢。

1 个答案:

答案 0 :(得分:2)

尝试

$this->get('form.factory')->createNamedBuilder(null, 'form', $defaultData)

而不是

$this->createFormBuilder($defaultData)