Yii2 - Save form in modal with Ajax - php

I have two models one is "register-products" (where I have a dropdown with all brands) and another form is "brands". I need to render form "brands" inside the form "register-products" to create a new brand using bootstrap Modal widow and it works, but I need the newly created brand to be available inside the dropdown of the register-products form so that I don't have to refresh the page each time.
At this moment what happens is that after creating a new brand is redirecting to the view with details of the new brand.
register-products form
<?php
Modal::begin([
'header' => 'Test',
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
Html::a('+', ['/brands/create'], ['id' => 'open_modal', 'class' => 'btn btn-success']);
js
$(function(){
$('#open_modal').click(function (){
$.get($(this).attr('href'), function(data) {
$('#modal').modal('show').find('#modalContent').html(data)
});
return false;
});
BrandsController
public function actionCreate()
{
$model = new Brands();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} elseif (Yii::$app->request->isAjax) {
return $this->renderAjax('create', [
'model' => $model
]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}

Related

How to create event with a specific date in fullcalendar philippfrenzel using select option

I'm trying to use the select option to create an event with a Modal with the selected date using Full Calendar - Philippfrenzel but I don't know how.
I already have an event Click which works but that it's not what I really want.
Controller:
public function actionRequisitar(){
$searchModel= new RequisicaoSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$events = [];
foreach(Requisicao::find()->all() as $requisicao){
$event = new \yii2fullcalendar\models\Event();
$event->id = $requisicao->id;
$event->title = $requisicao->motivo_requisicao;
$event->start = $requisicao->data_inicio_req;
$events[] = $event;
}
return $this->render('requisitar',[
'events'=>$events,
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
public function actionCreate()
{
$model = new Requisicao();
//$model->data_inicio_req=$date;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id, 'utilizador_id' => $model->utilizador_id, 'sala_id' => $model->sala_id]);
}
return $this->renderAjax('create', [
'model' => $model,
]);
}
Index:
<?= \yii2fullcalendar\yii2fullcalendar::widget(array(
'events' => $events,
'id' => 'calendar',
));
?>
Main.js
$(function () {
$('#modalButton').click(function () {
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
});
$(document).on('click', '.fc-day', function () {
var date = $(this).attr('data-date');
$.get('index.php?r=requisicao/create', {'date': date}, function (data) {
$('#modal').modal('show')
.find('#modalContent')
.load(data);
});
});
});
Inside the configuration of Index where you setup the fullcalendar widget:
<?= \yii2fullcalendar\yii2fullcalendar::widget(array(
'events' => $events,
'id' => 'calendar',
));
?>
You must add the property eventClick that triggers an JS function once an event is clicked.
You can do it like this:
<?= \yii2fullcalendar\yii2fullcalendar::widget(array(
'events' => $events,
'id' => 'calendar',
'eventClick' => new JsExpression('(event) => handleClick(event)'),
));
?>
Notice that handleClick has to be a real function that is declared in your javascript, you could change handleClick(event) for console.log(event) to check if it is working as you expect before creating the function.

add button to perform an action prior to sending to view page

I'm working on a program that is a reservation service for lab systems using Yii2.0. I've been using Yii for a little while but for some reason this one is stumping me
I have all of the systems listed in a gridview and I'd like to have a button in the actionColumn that will run the 'reserve' action and then show the view for the individual system.
I have the button added and it brings the user to the view page but I don't know what I need to do to have it run the reserve action first...or if it's even possible. I've tried pointing it to the reserve action in the controller but of course that looks for a view page rather than an action.
Here's some of the code from what I've been trying after looking through many pages of suggestions:
On the index page
['class' => 'yii\grid\ActionColumn',
'template' => '{reserve}',
'buttons' => [
'reserve' => function ($url, $model) {
return Html::a('<span class="glyphicon glyphicon-ok-circle"></span>',
$url,
[
'title' => 'Reserve',
'data-method' => 'post',
'data-pjax' => 0,
]);
}
],
'urlCreator' => function ($action, $model, $key, $index) {
return Url::toRoute(['cml/view', 'id' => $key]);
}
Function in Controller
public function actionReserve($id)
{
$model = $this->findModel($id);
if ($model->fkReservedTo == 1)
{
$model->fkReservedTo = Yii::$app->user->id;
// shouldn't you call save here
$model->save();
return $this->redirect(['view','id'=>$id]);
}
else
{
Yii::$app->session->setFlash('error', 'This system is not available to be reserved');
return $this->showAlert();
}
}
Any suggestions would be appreciated.
Change
return Url::toRoute(['cml/view', 'id' => $key]);
to
return Url::toRoute(['cml/reserve', 'id' => $key]);
in your urlCreator function.

Is it possible to get random values using ArrayHelper? Yii2

How do I get random values from another table? In my employee php I have 3 records, so there is 3 id values. In my ticket.php once I create a ticket it will automatically get the id value from the employee table but it is not randomise how do I do it?
Mine is currently getting the same value from employee whenever I create a ticket.
In the ticketcontroller.php
public function actionCreate()
{
$model = new Ticket();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
$model->time_start = date('y-m-d h:i:s');
$model->status = ('On Going');
$model->employee_respond_id = array_rand('id');
return $this->render('create', [
'model' => $model,
]);
}
}
In the _form.php
<?= $form->field($model, 'employee_respond_id')->dropDownlist(
ArrayHelper::map(Employee::find()->all(), 'id', 'id'),
[
'readOnly' => true,
'style' => 'width:200px'
]
); ?>
Try this way:
public function actionCreate()
{
$model = new Ticket();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
$employeeIDs = ArrayHelper::map(Employee::find()->all(), 'id', 'id'),
$model->time_start = date('y-m-d h:i:s');
$model->status = ('On Going');
$model->employee_respond_id = array_rand($employeeIDs);
return $this->render('create', [
'model' => $model,
'employeeIDs' => $employeeIDs
]);
}
}
_form.php
<?= $form->field($model, 'employee_respond_id')->dropDownlist(
$employeeIDs,
[
'readOnly' => true,
'style' => 'width:200px'
]
); ?>
Better use employee name as label and id as value in dropdown, still it will work for random function.

Yii2 custom client validation with ajax rendering in modal

I have a model with a custom validation method. For testing it always returns an error message.
public function rules()
{
return [
...
['staff_ids', 'each', 'rule' => ['string']],
[['staff_ids'], 'validateStaffIds'],
...
];
}
public function validateStaffIds($attribute, $params, $validator) {
$this->addError($attribute, 'There is an error in the staff ids');
}
In the view.php is the modal element
<p>
<?= Html::button('Add Ensemble Staff',
['value' => Url::to(['ensemble/add', 'id' => $model->id]),
'title' => 'Adding New Ensemble Staff',
'class' => 'showModalButton btn btn-primary']);
?>
</p>
<?php
Modal::begin([
'closeButton' => [
'label' => 'x',
],
'headerOptions' => ['id' => 'modalHeader'],
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
The js code which fires everything up...
$(function(){
$(document).on('click', '.showModalButton', function(){
if ($('#modal').data('bs.modal').isShown) {
$('#modal').find('#modalContent')
.load($(this).attr('value'));
} else {
//if modal isn't open; open it and load content
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
}
//dynamiclly set the header for the modal
...
});
});
And the ensemble controller which handles the add action
public function actionAdd($id)
{
$model = $this->findModel($id);
// in the post ( 'ensembleStaff_ids' => [0 => '2']); where the id actually is staff_id
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $id]);
} else {
return $this->renderAjax('add', [
'model' => $model,
]);
}
}
And the form which is injected by the js into the model (Url::to(['ensemble/add', 'id' => $model->id]), )
<?php $form = ActiveForm::begin(['id' => 'add-theater-stuff-form']); ?>
<?= $form->field($model, 'staff_ids')->widget(Select2::className(), [
'model' => $model,
'data' => ArrayHelper::map(app\models\TheaterStaff::find()->where(['theater_id' => $model->theater_id])->all(), 'staff_id', 'staff.fullname'),
'options' => [
'multiple' => true,
'prompt' => 'Ensemble Staff',
],
'pluginOptions' => [
'tags' => true
]
]); ?>
<div class="form-group">
<?= Html::submitButton('Add', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
Clicking on the Add Ensemble Staff Button works fine and brings up the modal window. The form itself works fine so far; also the default validation works. Even the custom validation is called, but return $this->renderAjax(...) isn't load in the modal window anymore; it is separately.
A picture showing the modal loaded, the result after submit and a modal with default validation.
I found a similar problem here. But adding an id to the form, doesn't solve the problem. So how to get the default validation showing up properly in the modal window? Does anyone have a clue?
Solution
Thanks for the response. For me the solution was:
Enable ajax in the form
<?php $form = ActiveForm::begin(['id' => 'add-ensemble-stuff-form', 'enableAjaxValidation' => true]); ?>
And to add the following logic in the controller
public function actionAdd($id)
{
$model = $this->findModel($id);
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
} else {
// in the post ( 'ensembleStaff_ids' => [0 => '2']); where the id actually is staff_id
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $id]);
} else {
return $this->renderAjax('add', [
'model' => $model,
]);
}
}
}
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}else{/* your code */}
add this in controller use yii\web\Response

Create new record using 2amigos SelectizeDropDownList in Yii2

I am trying to implement the 2amigos SelectizeDropDownList widget in a form to add new values to a table directly within the dropdown.
I am using the model Book and the Model Author so basically want to be able to add a new author in the book form.
This is the book controller at the update function:
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['index']);
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}
This is the form:
<?=
$form->field($model, 'author_id')->widget(SelectizeDropDownList::className(), [
// calls an action that returns a JSON object with matched
// tags
'loadUrl' => ['author/list'],
'value' => $authors,
'items' => \yii\helpers\ArrayHelper::map(\common\models\author::find()->orderBy('name')->asArray()->all(), 'id', 'name'),
'options' => [
'class' => 'form-control',
'id' => 'id'
],
'clientOptions' => [
'valueField' => 'id',
'labelField' => 'name',
'searchField' => ['name'],
'autosearch' => ['on'],
'create' => true,
'maxItems' => 1,
],
])
?>
And this is the function author controller:
public function actionList($query) {
$models = Author::findAllByName($query);
$items = [];
foreach ($models as $model) {
$items[] = ['id' => $model->id, 'name' => $model->name];
}
Yii::$app->response->format = \Yii::$app->response->format = 'json';
return $items;
}
The form works fine to load, filter, search and add new items.
But it is not inserting the new typed attribute in the author table.
Do I need to add something in the book controller?
How can I check if it is a new value or a change of an existing author?
Thanks a lot
I made it work with the following code, not sure the most elegant because i am checking the if the author_id is a number or a string.
In my case the author won't be a number anyway.
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post())) {
$x = Yii::$app->request->post('Book');
$new_author = $x['author_id'];
if (!is_numeric($new_author)) {
$author = new Author();
$author->name = $new_author;
$author->save();
$model->author_id = $author->id;
}
if ($model->save()) {
return $this->redirect(['index']);
}
} else {
return $this->render('update', [
'model' => $model,
'categories' => BookCategory::find()->active()->all(),
'publishers' => Publisher::find()->all(),
'copirights' => Copiright::find()->all(),
'authors' => Author::find()->all(),
]);
}
}

Categories