Yii drop down with ajax - php

So what I want to do is populate a dropdown in Yii framework with ajax using my database values in drop down. I using Kartik widget in it here is my dropdown code,
<?php $primaryfield = [1 => 'Business Development(Sales)', 2 => 'Graphic Design', 3 => 'Social Media Marketing', 4 => 'Web Development']; ?>
<?= $form->field($model, 'primaryfield')->widget(Select2::classname(), ['data' => $primaryfield,
'options' => ['placeholder' => 'Enter Your Primary Field', 'multiple' => false], 'pluginOptions' => ['tags' => false, 'tokenSeprators' => [',', ' '], 'maximumInputLength' => 20],])->label(false); ?>
I know everything about Ajax in PHP but don't know how to use it in Yii framework using Kartik widget I have all the primary fields value in my database but unfortunately, I am only able to display them in static basis not dynamic basis using ajax

If I get you clear, you want to have a drop-down list in which their items are dynamically generated by your database.
This is the way you can achieve with kartik dropdown widget.
I'll first create active form field which contains predefined categories as follows
<?php $form = ActiveForm::begin();
//Initialize predefined categories
$data = [
'1' => 'Business Development(Sales)',
'2' => 'Graphic Design',
'3' => 'Social Media Marketing',
'4' => 'Web Development',
];
?>
These field will prompt database to retrieve items for particular category via AJAX
<?= $form->field($model, 'primaryfield')->widget(Select2::classname(), [
'data' => $data,
'options' => ['placeholder' => 'Enter your primary field'],
'pluginOptions' => [
//'allowClear' => true
],
'pluginEvents' => [
"change" => "function() {
var id = $(this).val(); //extract the id of selected category
$.ajax({
method : 'GET',
dataType : 'text',
url : '../yourcontroller/populate?id=' + id,
success : function (response) {
var response = JSON.parse(response);
var myDropDownList = document.getElementById(\"model-item\");
$.each(response, function(index, value) {
var option = document.createElement(\"option\");
option.text = value;
option.value = index;
try {
myDropDownList.options.add(option);
}
catch (e) {
alert(e);
}
});
}
});
}",
],
]);
?>
<?= $form->field($model,'item')->dropdownList(
['prompt'=>'Select Item']
);
?>
Now create action in your controller that will query items from your database based on the category selected and return it to the Item field via ajax.
<?php
public function actionPopulate($id)
{
// the id above is the one selected from the category field so you can use
// that Id now to retrieve items from your item-field with ajax
/* in you case */
$results = Category::find()
->select('items')
->where(['id' => $id])
->asArray()
->all();
//these hard-coded values are for the demonstration
$results = [
'1'=>'maziwa',
'2'=>'ugali',
'3'=>'samaki',
'4'=>'kuku',
'5'=>'mtetea',
];
return json_encode($results);
}
?>
Hope this helps!

Related

Yii2 Krajee TreeViewInput widget , how to use multiple select?

I have three tables like this :
objects (id , name , tags , ...)
tags (id , name , ...)
object_tags(id , objectID , tagID)
I used krajee treeView input and in my "objects" form I have :
$form->field($model, 'tags')->
widget(\kartik\tree\TreeViewInput::className(),[
'name' => 'kvTreeInput',
'value' => 'false', // preselected values
'query' => Tags::find()->addOrderBy('root, lft')->name,
'headingOptions' => ['label' => 'تگ'],
'rootOptions' => ['label'=>'<i class="fa fa-building"></i>'],
'fontAwesome' => true,
'asDropdown' => true,
'multiple' => true,
'options' => ['disabled' => false]
]);
But I have no idea how should I write the codes in my controller or in my model!!!
In your action you should iterate over the post result
This is just a brief suggestion you must add the code related to your specific need
public function actionYourAction()
{
$post = Yii::$app->request->post();
if (!empty($post)){
$postTags = $post['tags'];
foreach ($postASCCId as $key => $value) {
$modelNew = new YourModel();
$modelNew->tag = $value;
$modelNew->save();
}
}
.....
}

I'm trying to retrieve from a database for a select box with cakePHP but the data isn't being retrieved properly

I am using cakephp 3.3
I have in the controller
$employee = TableRegistry::get('employees');
$allNames = $employee->find('list', array('employee_name' => array('employee_name') ) );
$allNames = $allNames->toArray();
$this->set('name', $allNames);
and in my template
<?= $this->Form->input('employee', array('type'=>'select','label' => false,
'options' => $name,'value'=>$name));?>
The only thing being retrieved and displayed is the number of entries i have in the database, $name only contains an array(1,2,3,4) when it should be actual people names.
Did you read the documentation about how find('list') works?'
$allNames = $employee->find('list', [
'keyField' => 'employee_name'
'valueField' => 'employee_name'
]);
$this->set('name', $allNames);
<?= $this->Form->input('employee', ['type'=>'select','label' => false,
'options' => $name]);?>
You can map id and value by keyField and valueField in list query
in your controller
$employee = TableRegistry::get('employees');
$allNames = $employee->find('list', array('valueField' =>employee_name','keyField'=>'employee_id' )); // correct employee_id with your table id field.
$this->set('name', $allNames);
In your View
<?= $this->Form->input('employee', array('type'=>'select','label' => false,
'options' => $name));?>

Trying to create a dependent combobox in yii using ajax

I am trying to create a dependent combobox system in my Yii application.
First combobox is populated with States and the second one is dynamically generated with ajax and renderPartial() method.
Code below:
View
<?php
$this->widget('ext.combobox.EJuiComboBox', array(
'model' => $adMulti,
'attribute' => 'state_id',
// data to populate the select. Must be an array.
'data' => CHtml::listData(State::model()->findAll(), 'id', 'name'),
'assoc' => true,
// options passed to plugin
'options' => array(
// JS code to execute on 'select' event, the selected item is
// available through the 'item' variable.
'onSelect' => 'getCities(item.value);',
// If false, field value must be present in the select.
// Defaults to true.
'allowText' => false,
),
// Options passed to the text input
'htmlOptions' => array(
'style' => 'height: 36px',
),
));
?>
<script type="text/javascript">
function getCities(state) {
$.ajax({
url: '<?php echo $this->createUrl('ad/ajaxCities'); ?>',
data: {state_name: state},
type: 'POST',
success: function (data) {
$('#city_id-carrier').html(data);
}
});
}
</script>
<div id="city_id-carrier" class="textboxes"></div>
AdController
public function actionAjaxCities()
{
$stateName = isset($_POST['state_name']) ? $_POST['state_name'] : FALSE;
if ($stateName) {
$state = State::model()->findByAttributes(array(
'name' => $stateName
));
$stateId = $state->id;
$cities = City::model()->findAllByAttributes(array(
'state_id' => $stateId
));
$this->renderPartial('_cities', array(
'cities' => $cities,
'stateId' => $stateId
), FALSE, TRUE
);
}
}
_cities.php
<?php
$this->widget('ext.combobox.EJuiComboBox', array(
'model' => AdMulti::model(),
'attribute' => 'city_id',
// data to populate the select. Must be an array.
'data' => CHtml::listData($cities, 'id', 'name'),
'assoc' => true,
// options passed to plugin
'options' => array(
// JS code to execute on 'select' event, the selected item is
// available through the 'item' variable.
// 'onSelect' => 'getLocalities(item.value);',
// If false, field value must be present in the select.
// Defaults to true.
'allowText' => false,
),
));
?>
The code is working and creating the combobox for the first time. But when I change the value in state combobox, something weird happens. A new combobox is created, but the values shown are still from the first combobox generated.
I am getting an error "TypeError: this.input is undefined" in Firebug Console.
I tried creating unique id for combobox using uniqid() but it isn't affecting the id of select element of the combobox.
If I change
$('#city_id-carrier').html(data)
to
$('#city_id-carrier').append(data)
it is working well but with multiple combobox generated.
Any ideas/suggestions to make this work?
I've found a solution to get this working. Instead of creating the combobox dynamically, place the combobox once and then populate it dynamically upon each request. Much like dependent dropdown.
A combobox is a combination of a dropdown and textbox. So, note down the id of the hidden dropdown and update it upon ajax update.
Code:
View:
<?php
$this->widget('ext.combobox.EJuiComboBox', array(
'model' => $adMulti,
'attribute' => 'state_id',
// data to populate the select. Must be an array.
'data' => CHtml::listData(State::model()->findAll(), 'id', 'name'),
'assoc' => true,
// options passed to plugin
'options' => array(
// JS code to execute on 'select' event, the selected item is
// available through the 'item' variable.
'onSelect' => 'getCities(item.value);',
// If false, field value must be present in the select.
// Defaults to true.
'allowText' => false,
),
));
?>
<script type="text/javascript">
function getCities(state) {
$.ajax({
url: '<?php echo $this->createUrl('ad/ajaxCities'); ?>',
data: {state_id: state},
type: 'POST',
beforeSend: function() {
$('#AdMulti_city_id_combobox').val(''); // emptying textbox in case a value is previously selected.
},
success: function (data) {
$('#AdMulti_city_id').html(data); // populating the hidden dropdown.
}
});
}
</script>
<?php
$this->widget('ext.combobox.EJuiComboBox', array(
'model' => $adMulti,
'attribute' => 'city_id',
// data to populate the select. Must be an array.
'data' => CHtml::listData(array(''), 'id', 'name'),
'assoc' => true,
// options passed to plugin
'options' => array(
'allowText' => false,
),
));
?>
AdController
public function actionAjaxCities()
{
$stateName = isset($_POST['state_id']) ? $_POST['state_id'] : FALSE;
if ($stateName) {
$state = State::model()->findByAttributes(array(
'name' => $stateName
));
$cities = City::model()->findAllByAttributes(array(
'state_id' => $state->id
));
$data = CHtml::listData($cities, 'id', 'name');
foreach ($data as $id => $name) {
echo CHtml::tag('option', array('value' => $id),
CHtml::encode($name), TRUE);
}
}
}

Doubts about parameter in the URL

I have the following form to the address below:
http://localhost/myapp/web/index.php?r=cashbook%2Faccomplishment
$form = ActiveForm::begin([
'id' => 'accomplishment-form',
'options' => ['class' => 'form-horizontal'],
'action' => Url::to(['/cashbook/accomplishment']),
'method' => 'get',
]);
$form->field($model, 'category_id')->dropDownList(ArrayHelper::map(
Category::find()->where(['user_id' => Yii::$app->user->identity->id])
->orderBy("desc_category ASC")
->all(), 'id_category', 'desc_category'),
['onchange'=>'this.form.submit()','prompt'=>'-- Select --']);
ActiveForm::end();
Who processes and generates the following URL:
http://localhost/myapp/web/index.php?r=cashbook%2Faccomplishment&Cashbook%5Bcategory_id%5D=18
But I need only the category_id value (selected in dropDownList). That is, the URL should be:
http://localhost/myapp/web/index.php?r=cashbook%2Faccomplishment&category_id=19
How to stay that way or get just the category_id
In view add registerJs:
$this->registerJs('var submit = function (val){
if (val > 0) {
window.location.href = "' . Url::to(['/cashbook/accomplishment']) . '/?category_id=" + val;
}
}', View::POS_HEAD);
And not use ActiveForm::begin... and all your code. Instead of use this:
echo Html::activeDropDownList($model, 'id_category', ArrayHelper::map(
Category::find()->where(['user_id' => Yii::$app->user->identity->id])
->orderBy("desc_category ASC")
->all(), 'id_category', 'desc_category'), ['onchange'=>'submit(this.value);','prompt'=>'-- Select --']);

YiiBooster Tabs widget content update with ajax call

I am using Yii Booster Yii extension for UI. I need to update the content of the tabs using ajax. Using below code I am able to get the content using renderPartial but instead I want to make ajax call and update the content.
$this->widget('bootstrap.widgets.TbTabs', array(
'type' => 'tabs',
'tabs' => array(
array('label' => 'Home', 'content' => $this->renderPartial('home', NULL, true), 'active' => true),
array('label' => 'Test', 'items' => array(
array('label' => 'Sub Tab 1', 'content' => $this->renderPartial('testpage', NULL, true)),
array('label' => 'Sub Tab 2', 'content' => 'some content ')
)),
)
)
);
Do I need to use jquery or something else to work with Yii Booster widgets ?. This is the first time I am using php/yii/extensions.
I am a bit confused so Yii Booster has integrated Bootstrap widgets so that they can be used with php. But for client side do I need to use jquery to manipulate bootstrap widgets ?
Are there any tutorials for using Yii Booster, I know the link to yii booster site, but there we just have simple examples nothing related to events, ajax.
Got this working. As #Sergey said I need to use 'shown' event. I gave ids to each tab to identify specific tab and load content. Here is the code
<?php $this->widget('bootstrap.widgets.TbTabs', array(
'id' => 'mytabs',
'type' => 'tabs',
'tabs' => array(
array('id' => 'tab1', 'label' => 'Tab 1', 'content' => $this->renderPartial('tab1', null, true), 'active' => true),
array('id' => 'tab2', 'label' => 'Tab 2', 'content' => 'loading ....'),
array('id' => 'tab3', 'label' => 'Tab 3', 'content' => 'loading ....'),
),
'events'=>array('shown'=>'js:loadContent')
)
);?>
We have 3 tabs, the content will be loaded using loadContent javascript function.
<script type="text/javascript">
function loadContent(e){
var tabId = e.target.getAttribute("href");
var ctUrl = '';
if(tabId == '#tab1') {
ctUrl = 'url to get tab 1 content';
} else if(tabId == '#tab2') {
ctUrl = 'url to get tab 2 content';
} else if(tabId == '#tab3') {
ctUrl = 'url to get tab 3 content';
}
if(ctUrl != '') {
$.ajax({
url : ctUrl,
type : 'POST',
dataType : 'html',
cache : false,
success : function(html)
{
jQuery(tabId).html(html);
},
error:function(){
alert('Request failed');
}
});
}
preventDefault();
return false;
}
Here we get the target, that should be the anchor element of the tab that we clicked, get the href value which should be the id that we configured. Decide the url based on this id, load content and update the div's. The id of div's are the same as href.
I haven't found way to load content of the initial active tab, there should be way to fire loadContent function, for now I have used renderPartial to get the content instead
I extended the TbTabs class with #Abdullahs example. It's tested with YiiBooster, but should work with other Bootstrap plugins as well.
Usage:
$this->widget(
'ext.ajaxTabs.widgets.ajaxTabs',
array(
'reload' => true, // Reload the tab content each time a tab is clicked. Delete this line to load it only once.
'tabs' => array(
array(
'label' => 'Static',
'content' => 'Static content'
),
array(
'label' => 'Static rendered',
'content' => $this->renderPartial('index', null, true),
),
// And finally AJAX:
array(
'label' => 'AJAX',
'content' => 'loading ....',
'linkOptions' => array('data-tab-url' => Yii::app()->createAbsoluteUrl('site/'))
)
),
)
);
/protected/extensions/ajaxTabs/widget/ajaxTabs.php:
<?php
Yii::import('bootstrap.widgets.TbTabs');
class ajaxTabs extends TbTabs
{
/**
* #var bool Reload the tab content each time the tab is clicked. Default: load only once
*/
public $reload = false;
public function run()
{
$id = $this->id;
/** #var CClientScript $cs */
$cs = Yii::app()->getClientScript();
$cs->registerScript(
__CLASS__ . '#' . $id . '_ajax', '
function TbTabsAjax(e) {
e.preventDefault();
var $eTarget = $(e.target);
var $tab = $($eTarget.attr("href"));
var ctUrl = $eTarget.data("tab-url");
if (ctUrl != "" && ctUrl !== undefined) {
$.ajax({
url: ctUrl,
type: "POST",
dataType: "html",
cache: false,
success: function (html) {
$tab.html(html);
},
error: function () {
alert("Request failed");
}
});
}
if(' . ($this->reload ? 0 : 1) . '){
$eTarget.data("tab-url", "");
}
return false;
}'
);
$this->events['shown'] = 'js:TbTabsAjax';
parent::run();
}
}
Its a new version to loadContent
function loadContent(e){
var targetUrl = e.target.getAttribute('data-tab-url');
var contentID = e.target.getAttribute('href');
$(contentID).load(targetUrl, function(){
$('.tabs').tabs(); //reinitialize tabs
});
e.preventDefault();
return false;}

Categories