2016-02-04 17 views
2

我试图通过REST API传递表单数据。该API构建在Symfony(2.7)中,实际的数据输入表单位于外部非symfony站点上。表单提交很好,直到我尝试传入一对“集合”。Symfony2:通过AJAX在Symfony之外添加集合

我一直在关注this tutorial,因此在我的Type类以下内容:

$form->add('event', 'collection', array(
    'type' => new AvRequestEventType(), 
    'allow_add' => true, 
    'by_reference' => false, 
)); 

$form->add('equipment', 'collection', array(
    'type' => new AvRequestEquipmentQuantityType(), 
    'allow_add' => true, 
    'by_reference' => false, 
)); 

我的数据输入表格看起来像这样(我将只显示为“事件”收集自“设备”集合代码基本上是相同的):

 var eventsPrototype = '<div id="event___name__" class="row"><div class="small-8 columns"><label for="event___name___location">Location<input type="text" id="event___name___location" name="[event][__name__][location]" maxlength="100" /></label></div><div class="small-4 columns"><label for="event___name___time">Time<input type="time" id="event___name___time" name="[event][__name__][time]" /></label></div></div>'; 
     var $eventsHolder; 
     var $addEventLink = $('<a href="#" class="add_event_link">Add Event</a>'); 
     var $newLinkLi = $('<li></li>').append($addEventLink); 

     $eventsHolder = $('ul.events'); 
     $eventsHolder.append($newLinkLi); 

     /* 
     count the current form inputs we have (e.g. 2), use that as the new 
     index when inserting a new item (e.g. 2) 
     */ 
     $eventsHolder.data('index', $eventsHolder.find(':input').length); 

     //add a new event form on page load 
     addEventForm($eventsHolder, $newLinkLi); 

     $addEventLink.on('click', function(event){ 
     event.preventDefault(); 

     //add a new event form 
     addEventForm($eventsHolder, $newLinkLi); 
     }); 

     function addEventForm($eventsHolder, $newLinkLi) { 
     // get the new index 
     var index = $eventsHolder.data('index'); 

     // Replace '__name__' in the prototype's HTML to 
     // instead be a number based on how many items we have 
     var newForm = eventsPrototype.replace(/__name__/g, index); 

     // increase the index with one for the next item 
     $eventsHolder.data('index', index + 1); 

     // Display the form in the page in an li, before the "Add a tag" link li 
     var $newFormLi = $('<li></li>').append(newForm); 
      $newLinkLi.before($newFormLi); 
     } 

当它的时间来提交表单,这是AJAX调用:

ajaxObject = { 
 
    url: $("#postform").attr("action"), 
 
    type: 'POST', 
 
    dataType: 'json', 
 
    xhrFields: { 
 
    withCredentials: true 
 
    }, 
 
    crossDomain: true, 
 
    data: $("#postform").serialize() 
 
}; 
 

 
$.ajax(ajaxObject) 
 
    .success(function(data, status, xhr) { 
 
    ... 
 
    }) 
 
    .fail(function(data, status, xhr) { 
 
    ... 
 
    }) 
 
    .always(function(data, status, xhr) { 
 
    ... 
 
    });

比方说,我创建了两个事件。需要注意的是事件实体有两个字段,位置和时间(在“时间”格式“)这是什么被作为数据发送这些事件的一个样本:

[event][0][location]:Event A 
[event][0][time]:22:22 
[event][1][location]:Event B 
[event][1][time]:22:11 

里面我Symfony的REST控制器我创建一个新的,未命名的形式来处理提交:

$form = $this->get('form.factory')->createNamed('', new AvRequestType(), $entity); 
$form->handleRequest($request); 

...validation and whatnot 

UPDATE:

生产日志产生尝试添加集合阵列如果出现以下错误:

"The Response content must be a string or object implementing __toString(), "array" given." 

我知道这意味着我必须以某种方式将集合数组转换为字符串,以便它被Symfony接受。但是如何?在将它传递给Symfony之前,我已经通过Javascript序列化了整个表单。我想,如果我在集合中有固定数量的项目,我可以使用JSON.stringify()每个表单字段,但这看起来不是一个非常优雅的解决方案。

回答

0

对此的解决方案是窗体需要有一个名称。

所以不是...

$form = $this->get('form.factory')->createNamed('', new AvRequestType(), $entity); 

...名称必须给予...

$form = $this->get('form.factory')->createNamed('myrequestform', new AvRequestType(), $entity); 

这让Symfony的(我想反正承担)承认所有领域属于到相同的请求。因此,而不是有一个请求是这样的:

eventDate:2016-02-01 
pickupDate:2016-02-29 09:45:00 
returnDate:2016-02-17 06:30:00 
attendees:32 
specialInstruction: special 
[event][0][location]:LA 
[event][0][time]:00:00 
[event][1][location]:LB 
[event][1][time]:11:11 

现在看起来是这样的:

avrequest[eventDate]:2016-02-01 
avrequest[pickupDate]:2016-02-29 09:45:00 
avrequest[returnDate]:2016-02-17 06:30:00 
avrequest[attendees]:32 
avrequest[specialInstruction]: sepcial 
avrequest[event][0][location]:LA 
avrequest[event][0][time]:00:00 
avrequest[event][1][location]:LB 
avrequest[event][1][time]:11:11 

当你考虑如何内的Symfony表单提交这是有道理的;每个表单元素的名称属性完全相同。

如果有人想要添加一个比这更优雅的解释,请随意。