I'm trying to make a simple search form (it will grow more complex soon so I'm using an ActiveForm here instead of simply passing GET parameters to the action method).
controller:
public function actionIndex()
{
$search_form = new UserSearchForm();
$search_form->load(Yii::$app->request->get(), $formName = '');
return $this->render('index', [
'search_form' => $search_form
]);
}
view:
<?php $form = ActiveForm::begin(['id' => 'search-form', 'method' => 'get']); ?>
<?= $form->field($search_form, 'q')->textInput(['name' => 'q']) ?>
<?= Html::submitButton('Search') ?>
<?php ActiveForm::end(); ?>
I'm using $formName = '' in controller and 'name' => 'q' in view to make the query string cleaner (simple q instead of UserSearchForm[q]).
Everything looks fine until first submit. I see a hidden q field in the form and after second submit the URL looks like /user?q=value1&q=value2, each submit adds another q to hidden fields. Is there a good way to get rid of those hidden fields? Or maybe the whole approach is wrong? I guess I'll need hidden fields there anyway (sorting, pagination etc).
You should simply set form action (if empty it will be the current url) :
<?php $form = ActiveForm::begin([
'id' => 'search-form',
'method' => 'get',
'action' => ['controller/index']
]); ?>
If you use for filtering the same action and controller as for displaying results, then
$form = ActiveForm::begin([
'id' => 'filter-form',
'method' => 'get',
'action' => Url::toRoute(\Yii::$app->request->getPathInfo())
]);
Related
In my Symfony 4.4 application I have the following code inside my controller. I am attempting to pre-populate the form based on previous submissions or data pulled from the database. Importantly, the DetailsType form includes multiple entities so it's not a clean 1 entity per form setup here.
$postVars = $request->request->all();
$formData = [];
if (count($postVars) > 0) {
$formData = $postVars['crmbundle_register_details'];
}
$form = $this->createForm(DetailsType::class, $formData, [
'attr' => ['class' => 'reCaptchaForm'],
]);
$form->setData([
'firstname' => $person->getFirstname(),
'lastname' => $person->getLastname(),
'email' => $person->getEmail(),
'country' => $person->getCountry(),
'timezone' => $person->getTimezone()
]);
My problem is if I try to pre-populate the form with setData above it does not work.
If I do it individually as below it works, but I can't see why. I'd prefer to pass setData an array rather than call setData multiple times.
$form->get('firstname')->setData($user->getFirstname());
$form->get('lastname')->setData($user->getLastname());
$form->get('email')->setData($user->getEmail());
$form->get('country')->setData($user->getCountry());
$form->get('timezone')->setData($user->getTimezone());
If the form contains many entities, it's better to have an embed form for each entity. In this case, you don't need to call the setters at all. The controller action code will be:
$form = $this->createForm(DetailsType::class, $someParentEntity, [
'attr' => ['class' => 'reCaptchaForm'],
]);
$form->handleRequest($request);
I have a typical Yii2 form for updating my model with a typical submit button. Next to it, I have a "Delete photo" button, that appears, if there is any photo to delete. The piece of view looks like that:
<?= Html::submitButton('Save changes', ['class' => 'btn btn-primary', 'name' => 'edit-button']) ?>
<?php $image = isset($page->photo) ? $page->photo->getImageUrl() : null; ?>
<?php if (isset($image)): ?>
<?= Html::a('Delete photo', ['delete-image', 'lab' => $lab->id, 'kind' => $page->kind], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Do you really want to delete this photo?',
'method' => 'post'
],
]) ?>
<?php endif; ?>
When there is a photo attached to this model and these two buttons appear next to each other, I must comment out 'method' => 'post' part in second button code. Because, if I don't this this, the second button is... submitting the form (just like the first one) instead of calling lab/delete-image route.
This is the first thing, that I don't understand. The entire code is either generated by Gii or copy-pasted from some Yii tutorials. Not even a bit of my invention and yet it works strangely. What am I missing?
It seems, that normal Html::a link (only styled by Twitter Bootstrap to look like a button, but not being a button at all) is submitting a form, instead of calling its action, when it contains data-method="post" attribute in element code. Is this a bug in Yii2 or am I missing something?
You need to place the link outside of the form. For calling actions from elements with data-method attribute yii has js function handleAction, and its documentation says:
This method recognizes the data-method attribute of the element. If the attribute exists, the method will submit the form containing this element. If there is no containing form, a form will be created and submitted using the method given by this attribute value (e.g. "post", "put").
For hyperlinks, the form action will take the value of the "href" attribute of the link.
Also if you use yii2 v2.0.3 or higher you can add data-params attribute which value should be JSON representation of the data, and this data will be submitted in request. As example:
echo Html::a('Delete image', ['delete-image'], [
'data' => [
'confirm' => 'Do you really want to delete this photo?'
'method' => 'post',
'params' => [
'lab' => $lab->id,
'kind' => $page->kind,
],
],
]);
In this example params array will be json encoded by yii2 internaly
I have written form tag of YII2 specific as
<?php $form = ActiveForm::begin(['id' => 'builder/saveform','options' => ['method' => 'post']]) ?>
but when i run this, my external javascript is catching an error showing
Error: Syntax error, unrecognized expression: #builder/saveform
What is the error
To change default action add it as the first argument in this format ['<controller>/<action>']
<?php $form = ActiveForm::begin(['action' => ['builder/saveform'],'options' => ['method' => 'post']]) ?>
Example from the Yii2 guide
Also, keep in mind that the method defaults to post, so specifying that is unnecessary.
$form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data'], 'action' => Yii::$app->urlManager->createUrl(['site/signup'])]);
You can also use this snippet for custom form action and other attributes. createUrl method will not affect your url pattern.
for the sake now i have written the following code
<?php $form = ActiveForm::begin(['action' => 'index.php?r=builder/saveform','options' => ['method' => 'post']]) ?>
it is working but is it the proper way to write???
I was able to do it by adding the action into the options like so
<?php $form = ActiveForm::begin(['id' => 'contact-form', 'options' => ['method' => 'post', 'action' => 'site/add']]); ?>
For Yii2
$form = ActiveForm::begin([
'id' => 'login-form',
'options'=>['autocomplete'=>'off','method' => 'post', ],
'action' => '/frontend/web/user-management/auth/login',
'validateOnBlur'=>false,
'fieldConfig' => [
'template'=>"{input}\n{error}",
],
]);
Since there is still no accepted answer, the exact answer to your question is in the Error:
"unrecognized expression: '#builder/saveform' ". You have your 'id' HTML tag of the Form being assigned a value of 'builder/saveform', which contains "/" - an illegal character in terms of HTML4 Specification. I suppose Yii has a "validation" in place resulting in your error.
Now, I believe you are trying to specify the relative URL for the Form submission. For that, please refer to Michael St Clair's answer.
I have 2 actions in my controller. First action to display form and fetch lists for the form fields from related HABTM models. Second action to perform searching and display results.
First action:
public function advancedSearch() {
$this->set($this->Restaurant->fetchRelatedData());
}
Also I have View for this action which displays the form: advancedSearch.ctp
echo $this->Form->create(null, array(
'type' => 'get',
'url' => '/restaurants/search', 'inputDefaults' => array(
'label' => false,
'div' => false
)));
echo $this->Form->input('companyname', array('label' => 'Name:'));
echo $this->Form->input('addr', array('label' => 'Address:'));
echo $this->Form->input('district_id', array('label' => 'District:'));
echo $this->Form->input('Station', array('label' => 'Subway station(s):'));
// etc.
echo $this->Form->end('Go!');
As you can see, this form sends data to my second action which performs actual searching.
I need to mention that I use pagination component in my search action and because of this I use the GET method.
My problem is that user may select some "simple" fields and some multiselect fields, send the form and after that he may want to refine search result.
So I need to implement functionality to pass data back to my form and populate fields with values which user has selected before.
How can I do that? Thanks.
Controller :
Yii::import("xupload.models.XUploadForm"); //enciora
$photos = new XUploadForm;
$this->render('create', array(
'model' => $model,
'photos' => $photos
));
create: <?php echo
$this->renderPartial('_form',
array(
'model'=>$model,
'photos' => $photos
)); ?>
_form: <?php
$this->widget( 'xupload.XUpload', array(
'url' => Yii::app()->createUrl( "/encionmentDetail/upload"),
//our XUploadForm
'model' => $photos,
//We set this for the widget to be able to target our own form
'htmlOptions' => array('id'=>'encionment-detail-form'),
'attribute' => 'file',
'multiple' => true,
//Note that we are using a custom view for our widget
//Thats becase the default widget includes the 'form'
//which we don't want here
'formView' => 'application.views.encionmentDetail._form',
)
);
?>
ERROR: Undefined variable: model or Undefined variable: photos . this are the errors coming
while creating. if one model is passed then it shows properly. Please help
Well, the problem is with this line 'formView' => 'application.views.encionmentDetail._form'
. if i remove this line then no error. what should i do ?
This could well be due to the fact that your _form and your inner form for
'formView' => 'application.views.encionmentDetail._form',
are the same. Use a different one in the form view. Its kind of getting recursive.
in controller file :-
<?php
Yii::import("xupload.models.XUploadForm");
$photos = new XUploadForm;
$this->render('create', array(
'photos' => $photos,
));
?>
in create a file passing a bot model in render file :-
<?php echo $this->renderPartial('_form', array('model'=>$model,'photo'=>$photo))
Important note : must same a active from id and extensition html option id
snow_walker absolutely right, but I want to give details.Well, maybe it will help someone.
Such case occurs when xupload widget view contains <form>, so when it renders it becomes nested in CActiveForm.
One of the way to fix it:
Place CActiveForm widget in create.php
Copy everything from standard xupload form view (…\protected\extensions\xupload\views\form.php) to your model _form.php (…\protected\views\somemodel_form.php)
Delete from _form.php
<?php if ($this->showForm) echo CHtml::beginForm($this -> url, 'post', $this -> htmlOptions);?>
and
<?php if ($this->showForm) echo CHtml::endForm();?>
The other thing is that you cannot change the attribute's value in the widget configuration. It has to be 'file' in the other way the Internal Server Error (500) occurs.