I am trying to add a from with a CKeditor widget imbedded via an AJAX request. The request itself works fine and returns the general partial view as I want it. Except for the Ckeditor widget, a normal textbox is return instead.
When the item is added to the group and the page is reloaded, the same partialView is being rendered (in a foreach with all group-items) and this time the CKeditor is nicely in place.
Posted my controller, initialization of the CKeditor and Scipt with AJAX request below. (The CKeditor is inlcuded in the _ContentItemHtml view)
I have taken a look at this, but I cannot call any CKeditor functions from JS since it is loaded as a widget.
Controller Action
public function actionCreateHtml($contentitemgroupid)
{
$model = new ContentItemHtml();
if (isset(Yii::$app->request->post()['ContentItemHtml'])) {
$item = Yii::$app->request->post()['ContentItemHtml'];
$model->contentitemgroupid = $contentitemgroupid;
$model->title = $item['title'];
$model->body = $item['body'];
$model->save();
// return $this->redirect(['edit', 'id' => $model->contentitemgroupid]);
}
else
return $this->renderPartial('_ContentItemHtml', ['model' => $model]);
}
Active form in view:
echo $form->field($model, 'body')->widget(CKEditor::className(), [
'preset' => 'custom',
'clientOptions' => [
'height' => 200,
'toolbarGroups' => [
['name' => 'basicstyles', 'groups' => ['basicstyles', 'cleanup']],
['name' => 'paragraph', 'groups' => ['templates', 'list']],
['name' => 'mode']]
]])->label(false);
Script.js
$('#addNewContentItem').on('click', function (e) {
e.preventDefault();
var url = 'create-' + $('#itemSelector').val().toLowerCase() + '?contentitemgroupid=' + $('#itemSelector').attr('contentitemgroupid');
$.ajax({
type: 'POST',
url: url,
cache: false,
success: function(res) {
$('.contentItemsManager').append('<div class="ContentItemContainer row">' + res + '</div>');
AddSaveEventListener();
AddSaveMediafileEventListener();
AddRemoveEventListener();
}
});
});
Use renderAjax instead of renderPartial. From the docs:
[renderAjax] Renders a view in response to an AJAX request.
This method is similar to renderPartial() except that it will inject into the rendering result with JS/CSS scripts and files which are registered with the view. For this reason, you should use this method instead of renderPartial() to render a view to respond to an AJAX request.
Related
I have some problems with my ajax call, I have a collection group and when I click on show link it should show me the collection's tasks.The problem is when I try to create new tasks for the current collection.I made 50% of the problem, because it creates the records in database, but something strange happen.
Form is already submitted even If I do not click the create button
After ajax call, it creates the records in database, but it does not append the newly created element, it shows me this:
Ajax call response
Here is my ajax script:
$(document).ready(function() {
// store task
$('#create-task').click(function (event) {
event.preventDefault();
$.ajax({
type: 'post',
dataType: 'json',
data: $('#create-task-form').serialize(),
success: function (data) {
$('#create-task-form').trigger('reset');
$('#createTaskModal').modal('hide');
$('.collections').append('<li>' + data.name + '</li>');
}
});
});
});
I did not set the url, because when I do that it shows me something like this, and I do not know why.
Duplicate collection/collection/id
Set the url
Routes:
// Collection routes
Route::prefix('collections')->middleware('auth')->group(function() {
Route::get('/', 'CollectionController#index')->name('collections.index');
Route::post('/', 'CollectionController#store')->name('collections.store');
Route::get('/{collection}', 'CollectionController#show')->name('collections.show');
Route::get('/{collection?}/edit', 'CollectionController#edit')->name('collections.edit');
Route::patch('/{collection?}', 'CollectionController#update')->name('collections.update');
Route::delete('/{collection?}', 'CollectionController#destroy')->name('collections.destroy');
Route::post('/{collection?}', 'CollectionController#storeTask')->name('tasks.store');
});
Controller
public function storeTask(Request $request)
{
$attributes = $request->validate([
'name' => 'required|min:3',
'description' => 'nullable|min:3',
'status' => 'required',
'due' => 'nullable|date'
]);
$attributes['collection_id'] = $request->collection;
$task = Task::create($attributes);
return Response::json($task);
}
PS: I can still create records, even the validation from back-end fails!
Based on your image your routing is wrong.
You get a 404 for trying to access collections/collections twice leading to a non existing URL of course.
A solution to this would be:
url: {{ url('/collections/25') }},
I need to a custom jQuery function in my TYPO3 backend when Im opening the "Page"-view.
I added a hook for the preProcess
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']
['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem']
['tx_dashboard'] =
\vendor\dashboard\Hooks\Backend\IconCorrection::class;
And in my IconCorrection I added
public function preProcess(PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row)
{
GeneralUtility::makeInstance(PageRenderer::class)
->addRequireJsConfiguration([
'paths' => [
'iconCorrection'=>'/typo3conf/ext/dashboard/Resources/Public/JavaScript/hidePreviewIcon.js',
],
'shim' => [
'iconCorrection' => ['jquery'],
],
]);
}
}
In my hidePreviewIcon.js I have a console.log
I want something like $(".btn").hide(); but for now just testing if the js is loaded.
In my dev-tools I see that the js was loaded, but the console.log wasnt executed.
What Im missing?
And can I just using addJsFile instead of addRequireJsConfiguration
Im using TYPO3 v8.7.2
EDIT:
I added
$renderer =\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Page\PageRenderer::class);
$renderer->addJsFile('/typo3conf/ext/trumpf_editordashboard/Resources/Public/JavaScript/hidePreviewIcon.js', 'text/javascript', false, false, '', true, '|', false, '');
to my preProcess()function.
Now the .js was loaded and executed a console.log();
But my
$(document).ready(){$(".btn").hide();
doesnt work. I think its executed too early
EDIT 2: Did the trick:
$(function(){
$('#typo3-contentIframe').ready(function(){
console.log("loaded");
$(".btn").hide();
});
});
I am making an ajax post request to controller where i fetch some details, now i don't want to send control back to ajax rather i want to pass data to some view.
return response()->json(['students' => $students]);
instead i want to do like this
return view('frontend.student.leadThanksPage',compact('students'));
ajax call
$.ajax({
type:"POST",
url:"{{ route('check.student.detail') }}",
data:$(this).serialize(),
success: function(data){
//....... },
error: function(data){
//........ }
});
and my route is
Route::post('fetch/student/detail', [ 'as'=>'check.student.detail',uses' => 'Frontend\Student\StudentController#fetchStudentDetail' ]);
Yes, You can render a view in the Laravel by returning view.
You need to configure the route whether the AJAX request is 'get' or 'post' like below,
Route::post('/ajax/GetContent', array(
'uses' => 'AjaxController#loadContent'
));
And you can do the implementation in your controller,
public function loadContent(Request $request )
{
// you can do your coding
return view('frontend.student.leadThanksPage')->with('students', $students);
}
}
Nothing needs to return in your Ajax response.
Happy Coding,
AK
I am using kartik select2 widget in my yii2 basic app. now i have to display province names in select2 widget on ajax call. It is working fine if i put it directly in form. however not working with ajax call.
Here are my form fields:
<?= $form->field($model, 'role')->dropDownList(
ArrayHelper::map(SubAdminRoles::find()->all(), 'id', 'role_name'),
[
'prompt' => 'Select Role',
'onchange' => '
if($(this).val() != 3) {
$( "#user_area" ).html("showLoading");
$.post( "fetch-area-list?id='.'"+$(this).val(),
function(data) {
$( "#user_area" ).html(data);
})
}'
]
) ?>
<div id="user_area">
</div>
And here is my action code
public function actionFetchAreaList($id) {
// $this->layout = 'none';
$data = [];
if($id == 1) {
$provinceList = \app\modules\adminpanel\models\ProvinceMaster::findAll(['status' => 1, 'is_deleted' => 0]);
foreach($provinceList as $obj) {
$data[$obj['id']] = $obj['province_name'];
}
//print_r($data);
//exit;
} else if($id == 2) {
$subDistrictList = \app\modules\adminpanel\models\SubDistrictMaster::findAll(['status' => 1, 'is_deleted' => 0]);
foreach($subDistrictList as $obj) {
$data[$obj['id']] = $obj['sub_district_name'];
}
}
echo '<label class="control-label">Select Province</label>';
echo Select2::widget([
'name' => 'state_2',
'value' => '1',
'data' => $data,
'options' => ['multiple' => true, 'placeholder' => 'Select Province']
]);
exit;
}
now when i try to get it through ajax i comes with display:none property so i am not able to show my select2 box.
I Also tried changing display:none to display:block in select2 class. In that case i got the select box, but is simple html multiple select box not select2 widget.
How to get it from controller using ajax call?
Thanks in advance.
It is bad practice to render html inside action.
In your case widget requires related JS for initialization. But it will not include in your response.
Move all your html to view area-list and render using following code:
public function actionFetchAreaList($id) {
$this->layout = false;
// ... preparing data
return $this->renderAjax('area-list', [
// ... some view data
]);
}
Method renderAjax renders a named view and injects all registered JS/CSS scripts and files. It is usually used in response to AJAX Web requests.
I also have similar project like this.
I have 2 combobox (using select2). When select a district from the first combobox. It will call an ajax request to get province list and fill into the second combobox.
Here is my solution:
Using Select2 widget as normally in form
Using javascript to call ajax request and change data of the second combobox.
My controller response data in json format.
$('#district-selector').on('change', function() {
var districtId = $(this).val();
var url = $(this).attr('tb_href');
$('#province-selector').html('');
$.get(
url,
{
city_id: districtId
},
function(response) {
if (response.error == 0 && response.data.length) {
$('#province-selector').append(new Option('', ''));
$.each(response.data, function() {
console.log(this.id + '--' + this.title);
var newOption = new Option(this.title, this.id);
$('#province-selector').append(newOption);
});
}
$('#province-selector').trigger('change');
}
);
});
Demo: demo link
I am working with Js helper to help me replace the contents of a "div" in my index.ctp with contents of another file changeto.ctp .
This application has a few check boxes with corresponding images. When I select a checkbox, the setting is stored in the database and the corresponding image is to be displayed. Similarly when unchecked, it is to be removed from the database and the image should disappear.
I am using the Js helper for this :
my changeto.ctp is subset of my index.ctp and has access to same variables and loads without any problems (except that any click/change events are just not responded to. The names of the Ids of the checkboxes are exactly same).
My index file contains the following Js code at the bottom of all Html:
$this->Js->get($change_checkbox1 )->event('click',
$this->Js->request(array(
'controller'=>'testing',
'action'=>'changeto'
), array(
'update'=>'#changeDiv',
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(array(
'isForm' => false,
'inline' => true
))
))
);
This is generating the following Jquery/javascript
$(document).ready(function () {$("#ck0_1_8").bind("click", function (event) {$.ajax({async:true, data:$("#ck0_1_8").closest("form").serialize(), dataType:"html", success:function (data, textStatus) {$("#changeDiv").html(data);}, type:"post", url:"\/mytest-site\/options\/testing"});
return false;});
}
My controller has a function called
changeto()
{
$this->layout = 'ajax';
}
the first time I click on this the checkbox this works without any problem. However any subsequent clicks don't work. The javascript is not even being called.
My questions are :
Any ideas ?
Will it help if I somehow ask cakephp to use on() / live() insead of bind() .If yes how ?
Thanks!!
Solved this by editing a cakephp core file:
lib/Cake/View/Helper/JqueryEngineHelper.php
line 184:
change
return sprintf('%s.bind("%s", %s);', $this->selection, $type, $callback);
to
return sprintf('%s.live("%s", %s);', $this->selection, $type, $callback);
cake version 2.2.2
You have to use on instead of bind as they suggest in this question .live() vs .bind()
That's what I did was create my own Helper on View/Helper add the following method:
public function onEvent($selector, $type, $callback, $options = array()) {
$defaults = array('wrap' => true, 'stop' => true);
$options = array_merge($defaults, $options);
$function = 'function (event) {%s}';
if ($options['wrap'] && $options['stop']) {
$callback .= "\nreturn false;";
}
if ($options['wrap']) {
$callback = sprintf($function, $callback);
}
return sprintf('$(document).on("%s", "%s", %s);', $type, $selector, $callback);
}
And use that method from my views:
echo $this->MyJs->onEvent('#creditcards', 'change', $eventCode, array('stop' => false));