Select2 ajax option using YII Framework - php

I am using Yii framework on a project and i am using an extension which uses select2 jquery. I am unable to grasp how the implementation for ajax works with this extension or the select2.
My ajax call returns the following json.
[
{"id":"1", "text" : "Option one"},
{"id":"1", "text" : "Option one"},
{"id":"1", "text" : "Option one"}
]
The yii extension enfolds the select2 extension as below
$this->widget('ext.select2.ESelect2', array(
'name' => 'selectInput',
'ajax' => array(
'url'=>Yii::app()->createUrl('controller/ajaxAction'),
'dataType' => 'json',
'type' => 'GET',
'results' => 'js:function(data,page) {
var more = (page * 10) < data.total; return {results: data, more:more };
}',
'formatResult' => 'js:function(data){
return data.name;
}',
'formatSelection' => 'js: function(data) {
return data.name;
}',
),
));
I found a related question from this Question! The link to the extension am using is YII select2 Extention!

So a week later i merged with the answer to this question.
First let me highlight how the select2 ajax or in my case the Yii ESelect Extension.
The ajax options for jquery are the same as for the Eselect Extention i.e. url,type and datatype altho there is a slight difference on the format returned after successfully querying.
As for the result set for Eselect/select2 expects two parameters to be returned. that is
id : data.myOptionsValue;
text : data.myOptionText;
Reference :: https://select2.github.io/options.html#ajax
if we want to customize the format for the result set that is retured we can go a head and extend the plugin by using
'formatResult' => 'js:function(data){
return data.name;
}',
'formatSelection' => 'js: function(data) {
return data.name;
}',
I also had an issue getting my head around how the extention was quering. A look around and i realised that we have two datatype jsonp and json these two datatypes will handle data differently.
Jsonp (json padding) allows sending query parameters when querying. As for my case i am not passing any other parameters e.g an authkey e.t.c. In my case i changed the datatype to json and returning a json with id and text as results. See below my working snippet.
echo CHtml::textField('myElementName', '', array('class' => 'form-control col-lg-12'));
$this->widget('ext.select2.ESelect2', array(
'selector' => '#myElementName',
'options' => array(
'placeholder' => 'Search ..',
'ajax' => array(
'url' => Yii::app()->createUrl('controller/ajaxAction'),
'dataType' => 'json',
'delay' => 250,
'data' => 'js: function(term) {
return {
q: term,
};
}',
'results' => 'js: function(data){
return {results: data }
}',
),
),
));

Related

Yii2 Dropzone.js init not working

I'm using yii2 with dropzonejs (perminder-klair/yii2-dropzone)
When i want to initialize the view with some data i got this error,
It seems like the init call is not proccessed
error
dropzone.min.js:1 Uncaught TypeError: this.options.init.call is not a function
at c.init (dropzone.min.js:1)
at new c (dropzone.min.js:1)
at HTMLDocument.<anonymous> (index.php?r=branches/upload:672)
at fire (jquery.js:3187)
at Object.fireWith [as resolveWith] (jquery.js:3317)
at Function.ready (jquery.js:3536)
at HTMLDocument.completed (jquery.js:3552)
my dropzonejs
<?= \kato\DropZone::widget([
'autoDiscover' => false,
'options' => [
'init' => "function(file){alert( ' is removed')}",
'url'=> 'index.php?r=branches/upload',
'maxFilesize' => '2',
'addRemoveLinks' =>true,
'acceptedFiles' =>'image/*',
],
'clientEvents' => [
'complete' => "function(file){console.log(file)}",
// 'removedfile' => "function(file){alert(file.name + ' is removed')}"
'removedfile' => "function(file){
alert('Delete this file?');
$.ajax({
url: 'index.php?r=branches/rmf',
type: 'GET',
data: { 'filetodelete': file.name}
});
}"
],
]);
?>
This plugin use Json::encode function for encoding options and because of this, in your code init encode as string. String is not a function.
You can simply use JsExpression for javascript function to prevent this.
When using yii\helpers\Json::encode() or
yii\helpers\Json::htmlEncode() to encode a value, JsonExpression
objects will be specially handled and encoded as a JavaScript
expression instead of a string.
This code should work.
<?= \kato\DropZone::widget([
'autoDiscover' => false,
'options' => [
'init' => new JsExpression("function(file){alert( ' is removed')}"),
'url'=> 'index.php?r=branches/upload',
'maxFilesize' => '2',
'addRemoveLinks' =>true,
'acceptedFiles' =>'image/*',
],
'clientEvents' => [
'complete' => "function(file){console.log(file)}",
// 'removedfile' => "function(file){alert(file.name + ' is removed')}"
'removedfile' => "function(file){
alert('Delete this file?');
$.ajax({
url: 'index.php?r=branches/rmf',
type: 'GET',
data: { 'filetodelete': file.name}
});
}"
], ]); ?>
it looks like this part in your options overwrites the Dropzone.js init function:
'init' => "function(file){alert( ' is removed')}",
The Yii2 plugin you are using ist simply encoding the options array:
Json::encode($this->options)
So your init is no function it is a string like this:
var options = { "init" : "function(file){alert( ' is removed')}" }
It is not possible to set the init option over this php plugin.
Edit: Thanks #CooPer for the correction, Yii2 isn't my favourite framework so I'm not very familiar with it. It's a good solution.

How to set an initial selection for an AJAX driven Select2 box with CakePHP?

I'm using select2 to let user choose stuff from list from ajax.
In adding to db it's working great, but I want to edit stuff. So I can still select stuff from my select2, but user should see what is the current value of select2.
I've tried to do something with InitSelect, but it didn't work, even after I've just passed data from php.
This is my Select2:
$(".personid").select2({
ajax: {
type: "post",
url: '/' + APP_PATH + '/Projects/find_person.json',
datatype: 'json',
quietMillis: '100',
data: function (term, page) {
return {
q: term.toUpperCase(), // wprowadzony ciag znakow - zawsze na uppercase
page_limit: 10,
};
},
results: function (data, page) {
var dane = {results: []};
$.each(data['data'], function (i, item) {
dane.results.push({
id: item['Person']['id'],
text: item['Person']['displayName']
});
});
return dane;
}
}
});
And this is my cake form input:
echo $this->Form->input('person_id', array(
'type' => 'text',
'value' => $projectcontact['Person']['id'],
'Placeholder' => 'Wybierz osobę',
'empty' => 'Wybierz osobę ',
'class' => 'form-control personid',
'label' => array(
'class' => 'col-md-4 control-label',
'text' => 'Osoba'
)
));
Can anyone help to make Select.js display current Persona name data from database in this?
With Select2 4.x
With Select2 4.x you're not supposed to use a text input element anymore, but a select element. Quote from the docs:
When using Select2 with remote data, the HTML required for the select is the same as any other Select2. If you need to provide default selections, you just need to include an option for each selection that contains the value and text that should be displayed.
<select class="js-data-example-ajax">
<option value="3620194" selected="selected">select2/select2</option>
</select>
https://select2.github.io/examples.html#data-ajax
So, as described, create a proper select input with a single selected option element, something along the lines of:
echo $this->Form->input('person_id', array(
'type' => 'select',
'options' => array(
$projectcontact['Person']['id'] => $projectcontact['Person']['displayName']
),
'selected' => $projectcontact['Person']['id'],
'class' => 'form-control personid',
'label' => array(
'class' => 'col-md-4 control-label',
'text' => 'Osoba'
)
));
Additionally you'll have to ensure that $projectcontact is being filled with the person according to the possible submitted person_id value, otherwise the selected value will not remain when rendering the form after submit.
Normally when creating a select element, you'd use a complete list of options, so that the form helper could pick the appropriate option automatically, based on the submitted value. Without such a list, you'll have to read and supply the specific person instead.
Here's some dummy code that demonstrates the priniciple:
$personId = $defaultPersonId;
if($this->request->is(array('post', 'put'))) {
$personId = $this->request->data('ModelName.person_id');
// ...
}
$projectcontact = $this->Person->findById($personId);
$this->set('projectcontact', $projectcontact);
See also
Cookbook > Core Libraries > Helpers > Form > Options for select, checkbox and radio inputs
Cookbook > Core Libraries > Helpers > Form > Creating form elements
Cookbook > Models > Retrieving Your Data > find(‘list’)

Converting jQuery using CakePHP's Javascript Helper

I'm having issues converting the following jQuery/AJAX call to CakePHP's JS Helper.
Here is what currently works:
<script type="text/javascript">
//<![CDATA[
$(document).ready(function () {
$("#DatabaseServerId").bind("change", function (event) {
var server_id = $("#DatabaseServerId").val();
$.ajax({
async:true,
dataType:"html",
evalScripts:true,
success:function (data, textStatus) {
$("#DatabaseEnvironmentId").html(data);
},
url:"\/apsportal\/servers\/get_environments/"+server_id
}
);
return false;
});
});
//]]>
</script>
Here is what I have thus far:
$data = $this->Js->get('#DatabaseServerId')->serializeForm(array('isForm' => true, 'inline' => true));
$this->Js->get('#DatabaseServerId')->event('change',
$this->Js->request(
array('controller' => 'servers', 'action' => 'get_environments'),
array(
'update' => '#DatabaseEnvironmentId',
'async' => true,
'type' => 'html',
'dataExpression' => true,
'evalScripts' => true,
'data' => $data,
)
)
);
The issue is that the parameter passed has an array key specified and narrows the usage of this action.
http://my.domain.com/servers/get_environments?data%5BDatabase%5D%5Bserver_id%5D=36
Since server_id is being used in other models, I would rather have this as generic as possible.
Note: I figure if I standardize to the JS Helper, if something changes in the future, I'll only have to change things once.
Per the comments, I used raw jQuery instead of CakePHP's methods.

Send model attributes to Yii controller using ajax

I'm currently using the following code to send an Ajax get request to my controller:
echo CHtml::ajaxLink('clickMe', array('ajax'), array('update'=>'#results'));
This works fine, the controller receives the request and updates the view accordingly.
Now, I want to send in this request attributes of the model, i.e. from model->getAttributes();
How should I do this? Create a JSON object of the attributes and send that with the request?
Just pass 'data' attribute and 'type' if needed:
echo CHtml::ajaxLink('clickMe', array('ajax'), array(
'update' => '#results'
'data' => CJSON::encode($model->attributes),
'type' => 'post',
));
This code just replaces #results contents with json. If you need something different, use 'success' instead of 'update' like this:
echo CHtml::ajaxLink('clickMe', array('ajax'), array(
'success' => 'function (response) {
// do everything you need
}',
'data' => CJSON::encode($model->attributes),
'type' => 'post',
));
Take a look at jquery ajax options for more information.

How to pass literal JavaScript code to Yii framework methods?

I am generating a checkbox using the corresponding method of CHtml, and I want to run some JavaScript code before and after the AJAX request. Here is the code:
echo CHtml::checkBox('markComplete', FALSE,
array(
'class' => 'markComplete',
'ajax' => array(
'type' => 'POST',
'url' => $this->createUrl('/events/events/MarkComplete'),
'data' => 'event_status='.$events['id'],
'beforeSend' => 'function(){ $(this).parent("TR").hide(); }',
'success' => 'function(resp) { $("#right").append(resp); }'
),
)
);
How can I tell Yii that beforeSend and success are JavaScript code and not plain strings?
Better option available starting from Yii 1.1.11
All framework classes now support custom JavaScript snippets through CJavaScriptExpression. Use it like this:
'ajax' => array(
'beforeSend' => new CJavaScriptExpression(
'function(){ $(this).parent("TR").hide(); }'
),
// ...
)
The option of prefixing strings with js: is still available by default, but it can now be disabled as required using an optional parameter on CJavaScript::encode.
Original answer
If you want to include literal JavaScript code as part of options, the convention in Yii is to prefix the code with js:. So you would write it like this:
'ajax' => array(
'type'=>'POST',
'url'=>$this->createUrl('/events/events/MarkComplete'),
'data'=>'event_status='.$events['id'],
'beforeSend' => 'js:function(){
$(this).parent("TR").hide();
}',
'success'=>'js:function(resp) {
$("#right").append(resp);
}'
),
)
Unfortunately this is not well documented, which is why people run into exactly this problem every now and then.

Categories