cakephp passing selection to JS Helper - ajax

I want to get the selected schoolFilter form value and place in [SELECTED VALUE HERE].
$data = $this->Js->get('#SchoolFilter')->serializeForm(array('isForm' => true, 'inline' => true));
$this->Js->get('#SchoolSchoolId')->event(
'change', $this->Js->request(
array('action' => 'assign_school_ads/', [SELECTED VALUE HERE], array(
'update' => '#results',
'data' => $data,
'async' => true,
'dataExpression' => true,
'method' => 'POST'
)
)
);
// School Filter
$schoolFilter = $this->Form->create('School', array('id' => 'SchoolFilter');
$schoolFilter .= $this->Form->input('school_id', array('label'=>'Schools', 'empty'=>'- select -');
$schoolFilter .= $this->Form->end();
I have seen variations on this question but without any clear answer, except to just forget using JS Helper. Is it possible within the context of JS Helper? And if not, can I get the value using regular JQuery, then inject it into JS Helper.

Use following code :-
$this->Js->get('#SchoolFilter');
$this->Js->event('change', $this->Js->request(array('controller'=>'put-ur-controller-ame-here','action' => 'assign_school_ads'),array('async' => true,'update' => '#results','method' => 'post','dataExpression'=>true,'data'=> $this->Js->serializeForm(array('isForm' => true,'inline' => true)))));
the serialize() function sends the form data to the php action so we can see which option was selected and decide what to update in the ajax call.
the form data will be found in $this->data in the action (just like after a form has been submited).
Don't forget to add $this->Js->writeBuffer(); in your layout just before the body closing tag. Otherwise all the ajax code will not be added to your page.

Related

Validate Select2 in Yii2 via AJAX

I have Yii2 application which uses the Kartik plugin to initialize Select2 dropdowns in forms.
I have one particular Select2 which uses AJAX call to get the data for the drop down options.
<?=
$form->field($model, 'court_house_id', ['enableAjaxValidation' => true, 'selectors' => ['input' => '#' . $id . "-court-house"],'template' => FormHelper::GenerateFieldTemplate([6])])
->widget(Select2::classname(), [
'options' => ['id' => $id . "-court-house", 'placeholder' => Yii::t('app', 'Search court house...')],
'hashVarLoadPosition' => \yii\web\View::POS_READY,
'pluginOptions' => [
'dropdownParent' => new JsExpression("$('#$modalWindowId')"),
'allowClear' => true,
'minimumInputLength' => 2,
'language' => [
'errorLoading' => new JsExpression("function () { return '" . Yii::t('app', 'Search...') . "'; }"),
],
'ajax' => [
'url' => app\components\UrlMaker::link('data/court-house-list'),
'dataType' => 'json',
'data' => new JsExpression('function(params) { return {q:params.term}; }')
],
'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
'templateResult' => new JsExpression('function(courthouse) { return courthouse.text; }'),
'templateSelection' => new JsExpression('function (courthouse) { return courthouse.text;}'),
]])
->label(Yii::t('app', 'Court House'), ['class' => FormHelper::GenerateLabelClassTemplate([3])]);
?>
Intentionally pasting all of the code, although most of it is irrelevant I would assume.
I have this loaded in multiple dynamically created forms thus all the strange ids and selectors. However, the form has different dropdown which controls whether some of the fields are shown (and required) or not. This particular field above is only shown in one of the scenarios which all the other variations of the form do not have it. So the model has the following validation:
[['court_house_id', 'staff'], 'required', 'on' => self::SCENARIO_ONE],
By the way staff is just a regular text field and everything works for it.
In order to change the scenario, I have the following line in the view with the form:
<?php $model->scenario = \app\models\MyModel::SCENARIO_ONE; ?>
The problem is that when I submit the form empty, the staff field gets marked in red as invalid but the court house is marked in green as valid although it is empty.
If I go into the model and remove the 'on' => self::SCENARIO_ONE part then everything works as expected - on empty submit the court house field also lights up in red but that would be a problem for the rest of my scenarios where this field is not needed.
Any ideas what might be causing the problem and how to resolve it?
Try to set the scenario in controller before calling save() method, for example
$model = new MyModel(['scenario' => MyModel::SCENARIO_ONE])

Yii2 ActiveForm Ajax Validation and submit

I have made an Active form with validation and ajax submit.
The form is created in view:
<?php $form = ActiveForm::begin([
'id' => 'login-form',
'layout' => 'horizontal',
'method' => 'post',
'enableClientValidation' => false,
'enableAjaxValidation' => true,
'validationUrl' => 'panel/validate',
'fieldConfig' => [
'options' => [
'tag' => false,
],
'template' =>'{input}<p class="help-block help-block-error ">{error}</p>'
],
]); ?>
The validation action:
public function actionValidate()
{
$model = new LoginForm();
$request = \Yii::$app->getRequest();
if ($request->isAjax && $request->isPost && $model->load(Yii::$app->request->post())) {
\Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
return $this->renderAjax('login', [
'model' => $model,
]);
}
When i leave the fields blank for example, or do not specify the captcha i can see the ajax response:
{"loginform-username":["Username cannot be blank."],"loginform-password":["Password cannot be blank."],"loginform-captcha":["Captcha cannot be blank."]}
However, those errors not getting shown under my form fields. The form fields are created like this:
<?= $form->field($model, 'username')->textInput()
If i turn off ajax validation, the erros are displayed. What can be wrong here?
I'm afraid there is no possible way to display error while turning off 'tag' = false in fieldConfig.
Even though it works for server-side validation, the main problem is how yii.activeForm.js updateInput() function for fields works. When ajax request is completed, the .js tries to find an outer tag (of field) with .field-<model>-<attribute> class selector and fetch error-div children. As long as there is no outer .field tag, no error message is append to form.
I'm not 100% sure about it, but this is my understanding from debugging yii.activeForm.js functionality.
Actually, here is the similar question in yii2/issues, where SilverFire explains that there is no way to achieve this.
ActiveForm fieldConfig options tag=>false will render class attribute without any tag

Yii how to send through ajaxButton the selected value of a combo?

echo CHtml::ajaxButton (Yii::t('Listing.Listing','Associa'),
$this->createUrl('listing/addAssociation', array("id" => $model->id, "itemId"=> '5' ) ),
array('update' => '#dataToUpdate')
);
i'm using this example code (and it's working), to send an id and an itemId ('5' fixed in the example), to addAssociation.
All is working, but I've the need to pass for itemId the result of a jQuery expression. something like
"itemId" = "js: $('#myDropDown option:selected').val();"
But in this case, the js expression is not evaluated and in actionAddAssociation i see that itemId is the literal string:
"js: $('#myDropDown option:selected').val();"
how to allow an user to select a combo, and the pass the selected value to an action based on this action ?
You have to pass that in the ajax option's data property:
echo CHtml::ajaxButton (Yii::t('Listing.Listing','Associa'),
$this->createUrl('listing/addAssociation', array("id" => $model->id)),
array(// these are ajax options
'data' => array('itemId'=> 'js: $("#myDropDown option:selected").val()'),
// and don't use semi-colon after val(), you can also pass id here itself
'update' => '#dataToUpdate'
)
);
You can try to use jQuery's ajaxPrefilter to add a function that will alter your data being passed through ajax.
First, you have to register the following script on your page's initialization:
jQuery.ajaxPrefilter(function(options, originalOptions, jqXHR) {
if (originalOptions['data'] && originalOptions['data']['requestId'] === "myDropDown") {
delete originalOptions['data']['requestId'];
originalOptions['data']['itemId'] = jQuery("#myDropDown option:selected").val();
options['data'] = jQuery.param(originalOptions['data']);
}
});
Here options is a complete settings object determined for jQuery.ajax(). I pass an additional requestId parameter to identify ajax request and, to make things simplier, a view could look like this:
<?php
print CHtml::dropDownList("myDropDown", 1, array(
1 => "First",
2 => "Second",
3 => "Third"
));
print CHtml::ajaxButton(Yii::t("Listing.Listing", "Associa"), Yii::app()->createUrl("listing/addAssociation"), array(
'data' => array(
'requestId' => "myDropDown",
'id' => $model->id
),
'update' => "#dataToUpdate"
));

CakePHP 2.1 - Callback functions for JsHelper / AJAX

Using the JsHelper for CakePHP 2.x, for each callback function, is it possible to have more than one selector being subject to various effects. For example, I am using:
echo $this->Js->submit('thumbs-up-green.jpg', array(
'id' => 'thumbs-up-green',
'before' => $this->Js->get('#thumbs-down-red')->effect('fadeOut'),
'success' => $this->Js->get('#thumbs-down-gray')->effect('fadeIn')
));
Let's say I want to apply an effect on #thumbs-down-gray in the before callback function as well (in addition to the effect on #thumbs-down-red which I currently have), what is the syntax for that? I have been searching around but documentation is limited for the JsHelper.
Additionally a simpler question, the JsHelper submit button / form seems to perform a line-break even if CSS display:none; is active. How do I get rid of that line-break?
I haven't found a very neat JsHelper solution, I don't think I can chain on additional elements and actions.
So I think for more complex callback functions the solution is to execute a pre-loaded function like:
'before' => 'someFunction();',
But if you just want to for example fadeOut multiple elements in one go then you could write it like:
'before' => $this->Js->get('#thumbs-down-red, #other-element')->effect('fadeOut'),
You have to set the "before"-action in a variable before the actual submit-call. Like this:
$before = $this->Js->get('#skadetyp_form')->effect('fadeOut', array('buffer' => false));
$before .= '$(\'#notice\').append(\'<div class="notice">Sending..<br/>' . $this->Html->image('load_bar.gif', array('alt' => 'Loading..')) . '</div>\')';
$complete = $this->Js->get('#notice div')->effect('fadeOut', array('buffer' => false));
$complete .= '$(\'#notice\').append(\'<div class="success">Succssfully seny!</div>\')';
echo $this->Js->submit('Send!',
array(
'update'=>'#skadetyp_form',
'complete' => $complete,
'before' => $before,
'error' => $error,
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(
array(
'isForm' => true,
'inline' => true
)
)
)
);

Drupal 7 + JS code through the AJAX

I had created several modules extending the UI elements of the FormAPI. This works fine when I render forms in a normal way (not AJAX). But if the rendered form is delivered though the AJAX request, JS script simply inserts the code via the $.html function. So I can't access elements of the document by their ID from the script evaluated by the $.html.
Is there any solution to pass JavaScript code through the Form/Ajax API?
I think jQuery("#new-id") (not $(..)) should take the newest dom elements.
You can use either the 'ajax' property of form api
$form['myitem'] = array(
'#type'=>'textfield',
'#ajax' => array(
'callback' => 'my_callback',
'wrapper' => 'new-id',
'method' => 'html',
'effect' => 'fade',
),
);
$form['myitem2'] = array(
'#type'=>'markup',
'#value'=>"<div id='new-id'> I'm #new-id </div>"
);
function my_callback(&$form, &$form_state){
$commands = array();
$commands[] = ajax_command_invoke('#new-id', 'html', array('<div id="new-id2">#new.id2 here!</div>'));
$commands[] = ajax_command_invoke('#new-id2', 'addClass', array('error'));
return array('#type' => 'ajax', '#commands' => $commands);
}
D7 ajax_commands:
http://api.drupal.org/api/drupal/includes--ajax.inc/group/ajax_commands/7
hope this help

Resources