I have made a patch to solve this issue. It adds a parameter to ajax options called "extraData" that contains an array of names and values for hidden inputs to be added dynamically. It behaves somewhat like jQuery.yii.submitForm():
//file: system.web.js.source.jquery.yii.js
...
addFormParams : function (element, params) {
var f = $(element).parents('form')[0];
jQuery.each(params, function(name, value) {
input = jQuery('input[name="'+name+'"][type="hidden"]')[0];
append = false;
if(!input) {
var input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", name);
append = true;
}
input.setAttribute("value", value);
if(append) {
f.appendChild(input);
}
});
},
serializeFormWithExtraParams : function (element, params) {
jQuery.yii.addFormParams(element, params);
return jQuery(element).parents("form").serialize();
}
...
//file: system.web.helpers.CHtml
...
/**
* Generates the JavaScript that initiates an AJAX request.
* @param array AJAX options. The valid options are specified in the jQuery ajax documentation.
* The following special options are added for convenience:
* <ul>
* <li>update: string, specifies the selector whose HTML content should be replaced
* by the AJAX request result.</li>
* <li>replace: string, specifies the selector whose target should be replaced
* by the AJAX request result.</li>
* <li>extraData: array, names and values to be added to a form as hidden inputs.</li>
* </ul>
* Note, if you specify the 'success' option, the above options will be ignored.
* @return string the generated JavaScript
* @see http://docs.jquery.com/Ajax/jQuery.ajax#options
*/
public static function ajax($options)
{
Yii::app()->getClientScript()->registerCoreScript('jquery');
if(!isset($options['url']))
$options['url']='js:location.href';
else
$options['url']=self::normalizeUrl($options['url']);
if(!isset($options['cache']))
$options['cache']=false;
if(!isset($options['data']) && isset($options['type'])) {
Yii::app()->getClientScript()->registerCoreScript('yii');
$extraData = '{}';
if(isset($options['extraData'])) {
$extraData = CJavaScript::encode($options['extraData']);
unset($options['extraData']);
}
$options['data']='js:jQuery.yii.serializeFormWithExtraParams(this,'.$extraData.')';
}
foreach(array('beforeSend','complete','error','success') as $name)
{
if(isset($options[$name]) && strpos($options[$name],'js:')!==0)
$options[$name]='js:'.$options[$name];
}
if(isset($options['update']))
{
if(!isset($options['success']))
$options['success']='js:function(html){jQuery("'.$options['update'].'").html(html)}';
unset($options['update']);
}
if(isset($options['replace']))
{
if(!isset($options['success']))
$options['success']='js:function(html){jQuery("'.$options['replace'].'").replaceWith(html)}';
unset($options['replace']);
}
return 'jQuery.ajax('.CJavaScript::encode($options).');';
}
...
And in the view:
...
<?php echo CHtml::beginForm(); ?>
...
... some inputs ...
...
<div class="action">
<?php
$htmlOptions['name'] = 'abc[def]';
$htmlOptions['id'] = 'abc_def';
$htmlOptions['type'] = 'submit';
$htmlOptions['value'] = 'delete';
$ajaxOptions['extraData'] = array($htmlOptions['name']=>$htmlOptions['value']);
echo CHtml::ajaxSubmitButton(Yii::t('app', 'delete marked'), '', $ajaxOptions, $htmlOptions);
?>
</div>
<?php echo CHtml::endForm(); ?>
...
If this form is submitted without javascript, the post value for button will be present, idem when with javascript.
Is it generic enough to be committed to framework source? If not, how could I extend it to get the same behavior?
Thanks