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));
Related
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 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.
I had created basic custom module. in that i just filled information form and that information will stored into the database. and that data i am showing into table format. now i want to edit and delete records from clicking links.
I want to call php function on clicking following links
links are:
while($data = $result->fetchObject()){
$rows[] = array(
$data->id,
$data->name,
$data->address,
$data->mob,
$data->gen,
$data->email,
$data->hob,
l('Edit' .$data->id,'/table', array('query' => array('edi'=>$data- >id))),
l('Delete' .$data->id, '/table', array('query' => array('del'=>$data->id))),
);
}
and the functions are as follows:
function form_values_edit($id){
$id_val = $id;
$my_object = db_select('demo_forms','n')
->fields('n')
->condition('id', $id_val )
->execute()
->fetchAssoc();
return drupal_get_form('demo_form', $my_object);
}
function delete_confirm($form, &$form_state, $id){
$form['delete'] = array(
'#type' => 'value',
'#value' => $id,
);
return confirm_form(
$form,
t('Are you sure you want to delete this?',
'/table',
t('This action cannot be undone'),
t('Delete'),
t('Cancel')
));
}
function delete_confirm_submit($form, &$form_state) {
$record = $form_state['values']['delete'];
if ($record ) {
$num_deleted = db_delete('demo_forms')
->condition('id', $record )
->execute();
drupal_set_message('The record has been deleted!');
}
$form_state['redirect'] = "/table";
}
Thanks
You cannot call a PHP function dynamically by clicking a link, as PHP is a server side language. HOWEVER if you load another page, before loading the page you can execute PHP code.
EDIT
if you need a PHP function dynamically, what I usually do (and this may be wrong according to some people) is call that function in an AJAX call. Note: I would generally use POST for this.
$.ajax(
url: 'url/to/php/function',
type: 'POST/GET',
data: {'data' : data},
success: function(res) {
// use the result stored in res
},
error: function(res) {
// use res to get the error result
}
);
Just add check for id field or another unique value in your php code and update or delete rows where id = ... With out unique value you can't do that. Describe your usability and post your html for more...
I use the following select2 Yii widget in my view to populate a drop-down list. Since the data necessary for the preparation of the select list consists of more than 2K records I use select2 with minimumInputLength parameter and an ajax query to generate partial result of the list based on user input. If I create a new record I have no problem at all. It populates everything fine and I can save data to my database. However I don't know how to load saved data back to this drop-down during my update action. I read somewhere that initselection intended for this purpose but I couldn't figure out how to use it.
Can someone help me out on this?
My view:
$this->widget('ext.select2.ESelect2', array(
'selector' => '#EtelOsszerendeles_osszetevo_id',
'options' => array(
'allowClear'=>true,
'placeholder'=>'Kérem válasszon összetevőt!',
'minimumInputLength' => 3,
'ajax' => array(
'url' => Yii::app()->createUrl('etelOsszerendeles/filterOsszetevo'),
'dataType' => 'json',
'quietMillis'=> 100,
'data' => 'js: function(text,page) {
return {
q: text,
page_limit: 10,
page: page,
};
}',
'results'=>'js:function(data,page) { var more = (page * 10) < data.total; return {results: data, more:more }; }',
),
),
));?>
My controller's action filter:
public function actionFilterOsszetevo()
{
$list = EtelOsszetevo::model()->findAll('nev like :osszetevo_neve',array(':osszetevo_neve'=>"%".$_GET['q']."%"));
$result = array();
foreach ($list as $item){
$result[] = array(
'id'=>$item->id,
'text'=>$item->nev,
);
}
echo CJSON::encode($result);
}
I use initSelection to load existing record for update in this way (I replaced some of your view code with ... to focus in main changes). Tested with Yii 1.1.14. Essentially, I use two different ajax calls:
View:
<?php
$this->widget('ext.select2.ESelect2', array(
'selector' => '#EtelOsszerendeles_osszetevo_id',
'options' => array(
...
...
'ajax' => array(
'url' => Yii::app()->createUrl('client/searchByQuery'),
...
...
'data' => 'js: function(text,page) {
return {
q: text,
...
};
}',
...
),
'initSelection'=>'js:function(element,callback) {
var id=$(element).val(); // read #selector value
if ( id !== "" ) {
$.ajax("'.Yii::app()->createUrl('client/searchById').'", {
data: { id: id },
dataType: "json"
}).done(function(data,textStatus, jqXHR) { callback(data[0]); });
}
}',
),
));
?>
Now in your controller you should receive parameters for ajax processing: query (q), as string, when inserting; id (id) as int when updating. Parameter names must be same as ajax data parameters (in this sample insert q; in update id) when read in $_GET. Code is not refactored/optimized:
Controller:
public function actionSearchByQuery(){
$data = Client::model()->searchByQuery( (string)$_GET['q'] );
$result = array();
foreach($data as $item):
$result[] = array(
'id' => $item->id,
'text' => $item->name,
);
endforeach;
header('Content-type: application/json');
echo CJSON::encode( $result );
Yii::app()->end();
}
public function actionSearchById(){
$data = Client::model()->findByPk( (int) $_GET['id'] );
$result = array();
foreach($data as $item):
$result[] = array(
'id' => $item->id,
'text' => $item->name,
);
endforeach;
header('Content-type: application/json');
echo CJSON::encode( $result );
Yii::app()->end();
}
Model - custom query and a little of order / security / clean :)
public function searchByQuery( $query='' ) {
$criteria = new CDbCriteria;
$criteria->select = 'id, ssn, full_name';
$criteria->condition = "ssn LIKE :ssn OR full_name LIKE :full_name";
$criteria->params = array (
':ssn' => '%'. $query .'%',
':full_name' => '%'. $query .'%',
);
$criteria->limit = 10;
return $this->findAll( $criteria );
}
EDIT:
It works out of box when update is preloaded with traditional HTTP Post (synchronous, for example with Yii generated forms). For async/Ajax updates, for example with JQuery:
Event / Trigger:
$('#button').on("click", function(e) {
...
... your update logic, ajax request, read values, etc
...
$('#select2_element').select2('val', id_to_load );
});
With this, initSelection will run again in async way with new id_to_load value, reloading record by id.
In your case and for your needs, initSelection could be complete different to avoid load record from db or you can use formatResult and formatSelection custom functions (are described in Load Remote Data sample source code). Reading documentation, I understand that initSelection's callback need JSON data with id and text elements to load properly or you could try to combine both concepts (this initSelection with your custom JS event/trigger call) (not tested):
'initSelection'=>'js:function(element,callback) {
// here your code to load and build your values,
// this is very basic sample
var id='myId';
var text='myValue';
data = {
"id": id,
"text": text
}
callback(data);
}',
Or directly on Trigger call:
$('#button').on("click", function(e) {
...
... ...
$("#select2_element").select2("data", {id: "myId", text: "MyVal"});
});
Hope that helps.
I tried doing that way, but couldn't do it
the solution I came up to get my record filled and selected was:
In case of the attribute having some data(in update mode or default value), I wrote some javascript that after document ready event, would fill the select with my data (just selected it ind pushed html in it), and made it selected, and then I rest( or update) the select to show my work.
I am new to CakePHP and I am trying to figure you how to make an asynchronous call from a CakePHP view to a function in the controller. I would like the controller function to return a string and have the view display this string. I would also like to to do this without using helpers. I have been trying to find examples on the web but have been unable to do so. Does anyone have a simple example? I am also using jQuery.
Thanks
CakePHP has a built-in JS Helper to help write aJax functions. The only catch is to include jquery in your head or cake will throw jQuery errors. Heres more information http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html
Your Form:
<?php
echo $this->Form->create('User', array('default'=>false, 'id'=>'YourForm'));
echo $this->Form->input('username');
echo $this->Form->submit('Check Username');
echo $this->Form->end();
?>
The Ajax Function: ('update'=>'#na') is the id of the element you want to update in your view.
<?php
$data = $this->Js->get('#YourForm')->serializeForm(array('isForm' => true, 'inline' => true));
$this->Js->get('#YourForm')->event(
'submit',
$this->Js->request(
array('action' => 'checkUsername', 'controller' => 'user'),
array(
'update' => '#na',
'data' => $data,
'async' => true,
'dataExpression'=>true,
'method' => 'POST'
)
)
);
echo $this->Js->writeBuffer();
?>
The Function in User Controller
function checkUsername(){
$this->autoRender = false;
$username = $this->User->find('first', array('conditions'=>array('User.username'=>$this->request->data['User']['username'])));
if ( $username == true )
echo 'Username is taken';
else
echo 'Username is not taken';
}
EDIT**
*If you want to use jQuery to do this and not the CakePHP Helper you can use aJax to call an action, then update your element like below*
$('#element').on('click', function() {
$.ajax({
url : '/controller/action',
type: 'POST',
success : function(response){
$('#elementToUpdate').html(response);
}
});
}
});
In your Controller Action you can return the "string" you would like to show in the view
function action(){
$string = 'Show this in the view';
return $string;
}
The above example would be executed when you "Click" an element with an id of "element" then upon "Success" would change element with id of "elementToUpdate" to the String "Show this in the view" Since it was returned from the controller action.