Rendering partial form - php

Is there any way to render partial view which contains a part of form that it's main part is in another view file with AJAX?
I exactly mean one form variable:
`<?php $form = ActiveForm::begin(['enableAjaxValidation' => true,]); ?>`
For Example :
Controller
public function actionOlddetform()
{
return $this->renderAjax('_olddet');
}
View
<?php $form = ActiveForm::begin(['enableAjaxValidation' => true,]); ?>
<?= $form->field($model, 'date')->input() ?>
<?= $form->field($model, 'annotations')->textarea(['rows' => 3]) ?>
<div id="details-form"></div>
<?php ActiveForm::end(); ?>
Part of form included with AJAX for details-form container depends on date value. I know how to check date and show any content of that partial view but when I want to include a part of form I get an error:
PHP Notice 'yii\base\ErrorException' with message 'Undefined variable: form'

It seems you forgot to actually pass the model into your view:
public function actionOlddetform()
{
return $this->renderAjax('_olddet', ['model' => $dataModel]);
}
And if you want to render "sub-views" from your main view, you need to pass the variables in there as well (even though I don't see a render call in your view):
<?= $this->render('_formPart', ['form' => $form, 'model' => $model]) ?>

Related

Cannot load form yii2

I am newbie to yii2. I am trying to create my simple form in yii2 to retrieve password. Here is class code:
<?php
namespace app\models;
use yii\base\Model;
class RetrievePasswordForm extends Model
{
public $email;
public function rules()
{
return [
['email', 'required'],
['email', 'email'],
];
}
}
Here is action code:
$model = new RetrievePasswordForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()){
return $this->render('retrievepassword-confirm', ['model' => $model]);
} else {
return $this->render('retrievepassword', ['model' => $model]);
}
My form looks like this:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$this->title = 'Retrieve password';
$this->params['breadcrumbs'][] = $this->title;
?>
<h1><?= Html::encode($this->title) ?></h1>
<p>We will send link to retrieve your password to the following email:</p>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'email')->textInput(['style'=>'width:200px'])?>
<div class="form-group">
<?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
The problem is that $model->load(Yii::$app->request->post()) always returns false, so when I am clicking "submit" button, page just reloads.
I am currently working without database. I am just creating form and trying to go to another form, when valid data received in model. Thanks for help.
Try explicitally assign the method and the action to the active Form
Then Assuming that your target action is named actionRetrivePassword
<?php $form = ActiveForm::begin([
'method' => 'post',
'action' => Url::to(['/site/retrivepassword']
); ?>
I'll go with I feel it's wrong, if this doesn't help, please give more information.
It's a registration form, so I assume you need email and password for that (since you have those columns in database). But you also declared public member $email in your model. This removes any value associated to $email from database. Therefore, remove this line:
public $email;

Yii2 rendering view doesn't work correctly

I have 3 tables:
Order
Ordered_number
Number
Ordered_number connects the other two - it has order_id and number_id columns.
In my Index Action, I want to render view named "call", where I have a form with choosing one order. When I submit which order I want, I want to go to actionCall and send there numbers connected with this order. Something isn't correct and I think I may be doing something wrong.
public function actionIndex()
{
$model = new \common\models\Order();
if ($model->load(Yii::$app->request->post())){
$numery = \common\models\Number::find()
->joinWith('ordered_number')
->where(['ordered_number.order_id' => $model->id]);
return $this->redirect(['/call', 'numery' => $numery]);
} else {
$this->render('call', ['model' => $model]);
}
}
When I open my actionIndex it displays a blank page instead of rendering a view that I want.
My "call" view:
<?php
use common\models\Customer;
use common\models\Order;
use yii\helpers\ArrayHelper;
use yii\helpers\Html;
use yii\web\View;
use yii\widgets\ActiveForm;
/* #var $this View */
/* #var $form ActiveForm */
/* #var $model Order */
var_dump($this);
die();
echo "<h1>Dodaj numery do przedzwonienia</h1>";
echo "Wybierz zamówienie, którego numery chcesz przedzwonić: ";
$form = ActiveForm::begin();
$form->field($model, 'id')->dropDownList(ArrayHelper::map(Customer::find()->all(), 'id', 'id'));
Html::submitButton("Przedzwoń", ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']);
ActiveForm::end();
I added var_dump in my view, and it displays it, but without var_dump and die() command, there is simply blank page without text I want to be next.
Missing return statement in else
return $this->render('call', ['model' => $model]);

How to use ActiveForm instance across Ajax requests in Yii 2?

For example we have this ActiveForm implementation in a sample view:
<?php $form = ActiveForm::begin(); ?>
<?=$form->field($model, 'first_name')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'last_name')->textInput(['maxlength' => true]); ?>
<div id="additional-form-fields"></div>
<a href="#" id="load-additional-form-fields">
Load more fields
</a>
<?php ActiveForm::end(); ?>
Now, I want to add more ActiveField / ActiveForm fields inside this form and place them in the #additional-form-fields element with Ajax, I'd do a simple jQuery callback:
$('#load-additional-form-fields').click(function() {
$.get('/site/additional-fields', {}, function(data) {
$('#additional-form-fields').html( data );
});
});
And the action additional-fields inside SiteController would be something as:
public function actionAdditionalFields() {
$model = new User;
return $this->renderAjax('additional-fields', [
'model' => $model,
// I could pass a 'form' => new ActiveForm, here, but it's a big NO-NO!
]);
}
And this works perfectly, only if I don't use any other ActiveField fields inside this action's view:
<?=$form->field($model, 'biography')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'country')->textInput(['maxlength' => true]); ?>
<?=$form->field($model, 'occupation')->textInput(['maxlength' => true]); ?>
Of course, I have to pass or instatiate $form somehow in this view, but it's NOT an option to use another ActiveForm::begin() / ActiveForm::end() anywhere inside this view since it will create another <form> tag and thus when I inject the Ajax response, I'll end up with with a <form> inside a <form> ...
Now, my question is as follows: Since I want to use ActiveForm, how can I share an instance of the ActiveForm through out multiple requests?
Is it doable / possible, if so, please help me realize how?
So far I have tried to put $form inside a session, but that's definitelly not working and not an option. Different than that, I've tried when passing parameters to renderAjax:
[
'model' => $model,
'form' => new ActiveForm,
]
In this case I get the following:
Form fields are created as they should with appopriate names and id's.
jQuery is loaded again (at the bottom of the response: <script src="..."> ... you get the idea)
I don't get the generated JavaScript for validation.
Is there anyway to share an instance of $form?
Okay, I have manage to do this, so I'll post the solution here and I'll open an issue on Github - might be useful in future versions.
1. Updates in yii2\widgets\ActiveForm.php
I've added a following property to the ActiveForm class:
/**
* #var boolean whether to echo the form tag or not
*/
public $withFormTag = true;
And I've changed run() method into this (check for // <-- added):
public function run()
{
if (!empty($this->_fields)) {
throw new InvalidCallException('Each beginField() should have a matching endField() call.');
}
$content = ob_get_clean();
if($this->withFormTag) { // <-- added
echo Html::beginForm($this->action, $this->method, $this->options);
} // <-- added
echo $content;
if ($this->enableClientScript) {
$id = $this->options['id'];
$options = Json::htmlEncode($this->getClientOptions());
$attributes = Json::htmlEncode($this->attributes);
$view = $this->getView();
ActiveFormAsset::register($view);
$view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);");
}
if($this->withFormTag) { // <-- added
echo Html::endForm();
} // <-- added
}
Thus if we instantiate a form like this:
$form = ActiveForm::begin([
'withFormTag' => false,
]);
It will not echo a <form> tag, but will render all ActiveField items and it will create their respective JavaScript/jQuery validators if $this->enableClientScript = true;.
2. Updates in my local view/file
After applying the previous fix in the base class, I needed to do the following in my view:
<?php $form = ActiveForm::begin([
'withFormTag' => false,
'id' => 'w0',
]); ?>
I had to pass the id parameter since every next instance of the ActiveForm class is incremented by 1, and I want my JavaScript/jQuery validators to be applied to the parent form, which by default starts from 0 -> w0.
And this is what did the trick!
Here's the Github issue as well: https://github.com/yiisoft/yii2/issues/12973

get input data in controller yii2?

i am trying get input field from a form in yii2. i need to use it in a controller depending on the value. i am trying to see the value using var_dump but it is not working. i am getting "NULL" as the value.. Or is there a way to make a form use different controllers.
controller
public function actionBlog()
{
$thumbs= new Thumbs;
$thumbs->user=Yii::$app->user->identity->email;
$thumbs->topic_id=Yii::$app->getRequest()->getQueryParam('id');
$ra=Yii::$app->request->post('rate');
var_dump($ra);
if(ra=='down'){
if ($thumbs->load(Yii::$app->request->post()) && $thumbs->validate()) {
$thumbs->load($_POST);
$thumbs->save();
return $this->refresh();
}
} else {
return $this->refresh();
}
return $this->render('blog',[
'thumbs' => $thumbs,
]);
}
this is my view
<?php $form = ActiveForm::begin(['id' => "contact-form"
]);
?>
<?= $form->field($thumbs, 'rate')?>
<?= Html::submitButton('Update', ['blog'], ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
i also tired using doing it like this
$rr=Yii::$app->request->post($thumbs)['rate'];
var_dump( $rr);
and i get this error:
Illegal offset type in isset or empty
You have a error in if(ra=='down') condition, '$' is missing.
If I remember right .. you should try
$ra=Yii::$app->request->post(['Thumbs']['rate']);

Yii2 in a form submission model is null after redirect

Upon form submission, if model is found in controller, a view is rendered with a set flash message but also with a customized message like hello <?= $model->username; ?> when applicable.
Everything worked fine, until I decided I'd be fun to add return $this->refresh(); to prevent form resubmission. Which ultimately throws Trying to get property of non-object in the view as model is righfully null.
As I see, the redirect method prevents the render method from being executed, hence the model variable from being sent to the view.
I'm using POST http method, I guesss I could change to GET if necessary. Have you any idea how to rework this?
CONTROLLER
public function actionIndividualSearch() {
$model = new Order();
$model->scenario = Order::SCENARIO_SEARCH;
if ($model->load($post = Yii::$app->request->post()) && $model->validate()){
//if ($model->load($post = Yii::$app->request->get()) && $model->validate()){
$model = Order::find()->where(['number' => $post['Order']['number']])->one();
$flash = $model ? ($model->status == Order::STATUS_COMPLETED ? 'orderCompleted' : 'orderNotCompleted' ) : 'orderNotFound';
Yii::$app->session->setFlash($flash);
return $this->refresh();
//return $this->redirect(['', 'model'=>$post['Order']['number']]);
}
return $this->render('individualSearch', [
'model' => $model,
]);
}
VIEW
<?php
use yii\widgets\DetailView;
use yii\helpers\Html;
?>
<div class="page-header">
<h1>Consulta tu Orden</h1>
</div>
<p>Por favor introdusca el número de orden impreso en su ticket.</p>
<?php echo $this->render('_search', ['model' => $model]); ?>
<?php if(Yii::$app->session->hasFlash('orderCompleted')): ?>
Hi <?= Html::encode($model->customer->first_name); ?> ...
<?php elseif(Yii::$app->session->hasFlash('orderNotCompleted')): ?>
Hi <?= Html::encode($model->customer->first_name); ?> ...
<?php elseif(Yii::$app->session->hasFlash('orderNotFound')): ?>
Dear Customer...
<?php endif; ?>
After refresh your Order model is empty and $model->customer is null.
And you're trying to get $model->customer->first_name in view.
The answer lied in using session variables, the flash type specifically. This allowed me to preserve variables between requests. Thanks to all involved.

Categories