Yii2 Kartik editable input value will only change after refresh - ajax

I use Kartik Editable input widget. I have a home model and tema model attribute here. Whenever I input and submit value in the field, the value won't change on-the spot but will only change after I refresh the page instead. What should I do? Thanks!
My controller :
public function actionIndex()
{
$searchModel = new HomeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
// table only has one row
$model= Home::find()->one();
// Check if there is an Editable ajax request
if (isset($_POST['hasEditable'])) {
// use Yii's response format to encode output as JSON
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
// read your posted model attributes
if ($model->load($_POST)) {
// read or convert your posted information. Based on the 'name' property set in the view. So this 'tema' of $model-> tema comes from 'name' property set in the view.
$value = $model->tema;
$model->save();
// return JSON encoded output in the below format
return ['output'=>$value, 'message'=>'output berhasil'];
// alternatively you can return a validation error
// return ['output'=>'', 'message'=>'Validation error'];
}
// else if nothing to do always return an empty JSON encoded output
else {
return ['output'=>'', 'message'=>'output gagal'];
}
};
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model'=>$model,
]);
}
The view
<?php
echo Editable::widget([
'model' => $model,
'attribute' => 'tema',
'value'=>$model->tema,
/*'asPopover'=>'false',*/
'type' => 'post',
'header'=>'tema',
'valueIfNull'=>'value-nya NULL',
'format'=>'link',
'size'=> 'lg',
'inputType' => Editable::INPUT_TEXT,
'editableValueOptions' => ['class' => 'text-success h3']
]); ?>
Another issue, whenever I used 'asPopover'=>'false', it shows no error but nothing happen when I click the supposedly editable-input field. The editable-inline field just won't show up. When I use the popOver option,the pop-up just automatically triggered without clicking and also it pop-up on the top left corner of the page. Only after I clicked on the editable widget that triggered the pop-up will it recorrect itself to the proper position. Is it a bug? I used the latest Yii2 with bootstrap 4, and I had set the global parameter in params.php config with 'bsVersion' => '4.x', as in the documentation

In the Controller, try this:
public function actionIndex()
{
$searchModel = new HomeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
if (isset($_POST['hasEditable']))
{
$tema = Yii::$app->request->post('editableKey');
$modelHome = Home::findOne($tema);
$posted = current($_POST['Home']);
$post = ['Home' => $posted];
if ($modelHome->load($post)) {
$modelHome->save();
$out = Json::encode(['output'=>$modelHome->tema, 'message'=>'']);
return $out;
}
return;
};
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model'=>$model,
]);
}

Related

Yii2 Kartik editable widget

I have a problem with my Kartik input text editable widget. It affected on the tema column in my table. The problem is, on my chrome developer tool it returns an "Internal server error" on the AJAX processing. The response header's content is : Content-Type: application/json; charset=UTF-8 but the connection remains close. Is there anything wrong with my code? Note : the initial value of the editable's label is NOT SET (which should be the value of "tema" column retrieved from my $model->tema). The model name is Home.
My HomeController :
public function actionIndex()
{
$searchModel = new HomeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$model = new Home;
// Check if there is an Editable ajax request
if (isset($_POST['hasEditable'])) {
// use Yii's response format to encode output as JSON
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$temaId=Yii::$app->request->post('editableKey');
$query= Home::find()->where(['id'=> $temaId])->one();
// read your posted model attributes
if ($model->load($_POST)) {
// read or convert your posted information
$value = $query->tema;
$value->save();
// return JSON encoded output in the below format
return ['output'=>$value, 'message'=>''];
// alternatively you can return a validation error
// return ['output'=>'', 'message'=>'Validation error'];
} else {
// else if nothing to do always return an empty JSON encoded output
return ['output'=>'', 'message'=>''];
}
};
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model'=>$model,
]);
}
The view file
use kartik\editable\Editable;
<?php
echo Editable::widget([
'model' => $model,
'attribute' => 'tema',
'type' => 'post',
'value'=>$model->tema,
'header'=>'tema',
'size'=> 'lg',
'inputType' => Editable::INPUT_TEXT,
'editableValueOptions' => ['class' => 'text-success h3']
]);
?>
Please help. Have spent two days on this. Thanks!

How can i skip unique field in Yii2?

I have a unique field that I check when editing or adding a new training course. But, for some reason, when I enter a value in a field, it does not show me a hint that the field is already taken.
In addition, I need to do this: when I change the values and did not change this unique field, but left it as it is, then the validor should not swear that the field is already taken.
Thank.
InfCourses Model:
public function rules()
{
return [
[['name', 'short_description', 'price', 'favorite', 'active', 'course_order', 'link'], 'required'],
[['price', 'active'], 'integer'],
[['favorite'], 'string'],
[['name', 'short_description', 'link'], 'string', 'max' => 255],
[['active'], 'exist', 'skipOnError' => true, 'targetClass' => InfStatuses::className(), 'targetAttribute' => ['active' => 'id']],
[['course_order'], 'integer', 'min' => 1],
[
['course_order'], 'unique',
'targetAttribute' => ['course_order'],
'filter' => ['!=', 'id', Yii::$app->request->get('id')],
],
];
}
Validator in InfCoursesController:
public function actionValidate()
{
$model = new InfCourses();
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
Part of form code:
<?php $form = ActiveForm::begin([
'enableAjaxValidation' => true,
'validationUrl' => 'validate',
'options' => [
'data-pjax' => true,
]
]); ?>
Your validation is simply incorrect. You're using Yii::$app->request->get('id') in your rules, which is probably main source of your problems. Model should not access request or web user component directly - it breaks MVC pattern. Also putting values directly in rules in this way may give you unexpected results. You should check what query is generated by this validator, because it is hard to guess what is happening with such twisted rule.
But it may be easier to fix actionValidate() and distinguish between validating of new record and validating existing record:
public function actionValidate($id = null) {
if (empty($id)) {
$model = new InfCourses();
} else {
$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);
}
}
Then you can limit your unique rule to:
[['course_order'], 'unique'],
Validator will be smart enough to detect that it is validating existing record and will not report unchanged fields values as duplicates. You just need to provide record ID in this action URL.
Well... I cut code below to each action: create/update.
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
Yii::$app->response->format = Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
Then remove validationUrl from form component. Inside model i make this rule [['course_order'],'unique']... Working fine...

Save data in ajax form yii2

I want to save data in two tables. The form being used is an ajax form with ajax request.
I want to obtain two values 'Task_ID' and 'Employee_ID' from the form and then save it to another table.
Controller Code is below
public function actionCreate()
{
$request = Yii::$app->request;
$model = new Activity();
$empModel = new Tasksemp();
//$tasksModel = new Tasks();
if($request->isAjax){
/*
* Process for ajax request
*/
Yii::$app->response->format = Response::FORMAT_JSON;
if($request->isGet){
return [
'title'=> "Create new Activity",
'content'=>$this->renderAjax('create', [
'model' => $model,
$model->finish_date = date('y-m-d'), //give default date as current along with date picker option
$empModel->Task_ID = $model->Task_ID, //<----Error here. The value of Task_ID and Employee_ID is null.
$empModel->Employee_ID = $model->Employee_ID,
$empModel->save(false),
]),
'footer'=> Html::button('Close',['class'=>'btn btn-default pull-left','data-dismiss'=>"modal"]).
Html::button('Save',['class'=>'btn btn-primary','type'=>"submit"])
];
}else if($model->load($request->post()) && $model->save()){
return [
'forceReload'=>'#crud-datatable-pjax',
'title'=> "Create new Activity",
'content'=>'<span class="text-success">Create Activity success</span>',
'footer'=> Html::button('Close',['class'=>'btn btn-default pull-left','data-dismiss'=>"modal"]).
Html::a('Create More',['create'],['class'=>'btn btn-primary','role'=>'modal-remote'])
];
}else{
return [
'title'=> "Create new Activity",
'content'=>$this->renderAjax('create', [
'model' => $model,
'empModel' => $empModel,
]),
'footer'=> Html::button('Close',['class'=>'btn btn-default pull-left','data-dismiss'=>"modal"]).
Html::button('Save',['class'=>'btn btn-primary','type'=>"submit"])
];
}
}else{
/*
* Process for non-ajax request
*/
if ($model->load($request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->Activity_ID]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
}
I need to obtain the two values after the ajax form has been saved or anyway way I can get the values and save in the ajax form?
Any help would be appreciated! Thank you
I think you wrote incorrect code.
Is not recommend (strictly) perform "=" operator and methods within [ ... ] statement.
Then you not load any values to Activity model.
if ( $request->isGet ){
$model->finish_date = date('y-m-d'); //give default date as current along with date picker option
// loading values from form
$empModel->Task_ID = $request->get('name_of_form_input_that_contains_Task_ID');
$empModel->Employee_ID = $request->get('name_of_form_input_that_contains_Employee_ID');
$empModel->save(false);
return [
'title' => "Create new Activity",
'content' => $this->renderAjax('create', [
'model' => $model,
// any other data
]),
'footer' => '' // ..
];
}

Passing variable to the view from zend form using AJAX load

controller:
public function searchAction()
{
$form = new Application_Form_Search;
$k = $form->getValue('keyword');
$car = new Application_Model_Car();
$mapper = new Application_Model_CarMapper();
$this->view->cars = $mapper->search($keyword);
}
form
<?php
class Application_Form_Search extends Zend_Form {
public function init(){
$this->setMethod('post');
$this->addElement('text', 'keyword', array(
'required' => true,
'label' => 'Keyword:'
));
$this->addElement('button', 'submit', array(
'required' => false,
'ignore' => true,
'label' => 'Search'
));
}
}
?>
original view page
$(document).ready(function(){
$("#submit").click(function(){
$("#main").load('/cars/search');
});
});
Here I am trying to return the search view at the "id=main" section in the original view page by using .load()
In the search view, <?=$this->keyword?> is showing null
it seems like there's problem fetching the keyword field from the form
Ok, you need to set the second variable of .load to send the data. At present you aren't sending the data to the .load function
so it would be more like this. This is assuming that you have id of keyword
$("#main").load('/cars/search', {'keyword':$('input#keyword').val()});
or you could use
$("#main").load('/cars/search', {'keyword':$('[name="keyword"]').val()});
Please see
http://api.jquery.com/load/
Also remember to escape the value so people can't send malicious code through your form.
Hope that helps

Yii2 - How to render the index view plus the create view all in the same page

Greetings,
So far i have made Yii2 applications always rendering one view per action in some Controller.
But now i need to render 2 view files, the index and the create in the same screen.
In Yii1.xx there was renderPartial(), and in Yii2 now there is render() as substitute but don't know how to use it. I know the syntax is somewhat like app/Controller::render() but it doesn't ring a bell to me.
My actionIndex in my SiteController is:
public function actionIndex()
{
$searchModel = new TubeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->redirect(Url::toRoute('tube/index'), [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
This action loads the tube/index page as the starting page of the app. I want to join in the load the create action. Is it possible -> two php files rendering in the same screen at statup.
many thanks...
It's not clear from your question what you are actually trying to achieve, so I'll propose two solutions, based on two very different scenarios. In both scenarios, you will need to configure the action parameter of your form to point to tube/create, otherwise your form will not submit properly.
Scenario 1 - You want the tube/index view to be rendered when your user visits site/index
Since the view tube/index seems to be about creating new models, I'll call it tube/create instead, for simplicity.
Redirecting from your index page would seem to me to be bad practice. It will double the load on your server, and the user may be confused as to why they are being redirected. The simplest way to achieve this would be just to render the tube/create view in the index action of your site controller, like this;
public function actionIndex(){
$searchModel = new TubeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$model = new Tube();
$model->load(Yii::$app->request->post());
$model->save();
return $this->render('#app/views/tube/create', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}
Scenario 2 - You want to render two views on the same page, one to view the results of some kind of search, and the other to create a new model. This is what you might have used renderPartial() for in Yii1. you would do it like this;
I'm sticking with rendering tube/create in the site/index action.
public function actionIndex(){
$searchModel = new TubeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$model = new Tube();
$model->load(Yii::$app->request->post());
$model->save();
return $this->render('//tube/index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}
You would then just render the two separate partial views in your tube/index view file, like this.
/** tube/index **/
echo $this->render('//tube/view', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,]);
echo $this->render('//tube/create', [
'model' => $model]
);
The two scenarios assume that your view files are located in the views/tube folder, and that you have already loaded the necessary models with a use statement at the top of the controller file.
I SOLVED IT BY MYSELF.
SITECONTROLLER CODE:
public function actionIndex()
{
return $this->redirect(Url::toRoute('tube/index'));
}
TUBECONTROLLER CODE:
public function actionIndex()
{
$searchModel = new TubeSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$model = new Tube();
if ($model->load(Yii::$app->request->post())) {
$model->save();
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}
This way the index and create view are together in the same page and every thing works ok.

Resources