Yii2 Kartik editable widget - ajax

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!

Related

Yii2 Kartik editable input value will only change after refresh

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,
]);
}

CakePHP 3.0 throwing 'field required' error on non-empty field

I'm having difficulty with my CakePHP 3.0 site throwing an error when it shouldn't. I'm building an "Add Page" form, shown below:
echo $this->Form->create($newpage);
echo $this->Form->control('title');
echo $this->Form->control('content');
echo $this->Form->button('Save');
echo $this->Form->end();
The title and content are required. Once the form is submitted, 'title' is used to generate a page 'name', which is currently just the title in lowercase and with spaces removed (so "About Us" would have the name "aboutus"). This name is also saved, but must be unique (eg if you had pages with titles "No Space" and "NOSpace" they would both end up with the name "nospace" even though the titles are unique).
I have the following validation rules in PagesTable.php:
public function validationDefault(Validator $validator)
{
$validator = new Validator();
$validator
->requirePresence('title','content')
->lengthBetween('title', [0, 50])
->add(
'name',
['unique' => [
'rule' => 'validateUnique',
'provider' => 'table',
'message' => 'Not unique']
]
);
return $validator;
}
The form is submitted to the controller, which contains this:
public function add($mainpage_id = null) {
$newpage = $this->Pages->newEntity();
if ($this->request->is('post')) {
$newpage = $this->Pages->patchEntity($newpage, $this->request->data);
// Get page name by removing spaces from title
$name = strtolower(str_replace(' \'\"', '', $newpage->title));
// Get navigation order by getting number of current siblings, and adding 1
$siblings = $this->Pages->find('all')
->where(['parent_id' => $newpage->parent_id])
->count();
$nav_order = $siblings + 1;
$newpage = $this->Pages->patchEntity($newpage, ['name' => $name, 'nav_order' => $nav_order]);
if ($newpage->errors()) {
$errors = $newpage->errors();
if(isset($errors['name'])) {
$this->Flash->error('The title you have entered is too similar to one that already exists. To avoid confusion, please choose a different title.');
}else {
$this->Flash->error('Please correct errors below');
}
}else {
$this->Pages->save($newpage);
$page_id = $newpage->id;
$this->Flash->success('Page created');
return $this->redirect('/admin/pages/index');
exit;
}
}
$this->set(compact('newpage'));
$this->set('_serialize', ['newpage']);
}
However, when I try to submit a page, I get "This field is required" on the title field even if I've entered a title. In fact, it won't let me submit the form without entering a title (a message pops up saying "Fill out this field"), but then it throws the error.
Can anyone see what I'm doing wrong?
Codebase looks good. However, this might be not obvious behavior: calling patch entity method validate the passed patch data.
So the first time your patch is validated here:
$newpage = $this->Pages->patchEntity($newpage, $this->request->data);
and second time it's validated here:
$newpage = $this->Pages->patchEntity($newpage, ['name' => $name, 'nav_order' => $nav_order]);
and as second patch have no title, then validator said that it missed. To fix this you need to run patch once with all the data, i.e.:
$data = $this->request->data();
// Get page name by removing spaces from title
$data['name'] = strtolower(str_replace(' \'\"', '', $data['title']));
// Get navigation order by getting number of current siblings, and adding 1
$siblings = $this->Pages->find('all')
->where(['parent_id' => $data['parent_id']])
->count();
$data['nav_order'] = $siblings + 1;
$newpage = $this->Pages->patchEntity($newpage, $data);
Hope you understand the idea, and it'll help.
UPDATE: just noticed that there might be no parent_id in request... You can move this logic into afterSave callback in PagesTabe:
public function afterSave(Event $event, EntityInterface $entity) {
$siblings = $this->count()
->where(['parend_id '=> $entity->parent_id]);
// updateAll won't trigger the same hook again
$this->updateAll(
['nav_order' => ++$siblings],
['id' => $entity->id]
);
}

I need correct example for ajax send and received data in zend framework 3

Example for send and received data between ajax function and action of controller in Zend framework 3
Here is a simple example of an ajax request using ZF3. You may give a try with this one. In this example we would use ZF3's default Application module.
Lets assume we would retrieve data via a ajax call from the following url.
http://yoursite.com/title
Lets create an action method for the title route in the IndexController.
public function titleAction()
{
// Initialize view
$view = new ViewModel();
// Checks if this is a Javascript request
$xmlHttpRequst = $this->getRequest()->isXmlHttpRequest();
if (! $xmlHttpRequst) {
die('Bad request');
}
/**
* Here we may pull data from database but for tests
* here we make an array of titles for the view
*/
$titles = [];
for ($i = 0; $i < 10; $i++) {
$titles[] = "Lorem ipsum dolor {$i}";
}
// Set data to be used in the view
$view->setVariable('titles', $titles);
/**
* Tell the renderer not to show the layout
* by setting setTerminal to true
*/
$view->setTerminal(true);
return $view;
}
We created a method, we need creating a view template for it.
view/application/index/title.phtml
<?php
foreach ($titles as $title) {
echo '<h2>' . $title . '</h2>';
}
Now we would create another action method in the IndexController from where we would make the ajax call.
http://yoursite.com/text
So lets make that action method too...
public function textAction()
{
return new ViewModel();
}
and view template would be like so
view/application/index/text.phtml
<h1>Handling ajax request</h1>
<button onclick="showTitle()">Show Title</button>
<div id="box"></div>
<?php
// Set url
$url = $this->serverUrl('/title'); // http://yoursite.com/title
// This is for the "url" catch
echo "<script>" . PHP_EOL;
echo "\tvar url = '{$url}';" . PHP_EOL;
echo "</script>" . PHP_EOL;
?>
<script>
function showTitle() {
$.get(url, function(data){
$('#box').html(data);
})
.done(function(){
console.log('Done!');
})
.fail(function(){
console.log('Failed!');
});
}
</script>
This script needs jQuery Javascript library to make the ajax call. So make sure that script is added in your view/layout/layout.phtml.
The last thing we need is to set up routes for the /title and /text. Lets add those two routes to the route section of module/Application/config/module.config.php
'title' => [
'type' => Literal::class,
'options' => [
'route' => '/title',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'title',
],
],
],
'text' => [
'type' => Literal::class,
'options' => [
'route' => '/text',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'text',
],
],
],
Let us know if it makes you happy!

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

Resources