My autocomplete is not working and I can't spot the error.
Jquery:
<script>
$(function() {
$('#autoComplete').autocomplete({
//source: "/groceries/items/autoComplete", ///This works but response isn't formatted correctly'
//dataType: "json"
minLength: 2,
source: function( request, response ) {
$.ajax({
url: "/groceries/items/autoComplete",
dataType: "jsonp",
data: {
featureClass: "P",
style: "full",
maxRows: 12,
term: request.term
},
success: function( data ) {
response( $.map( data, function( el ) {
return { label: el.id, value: el.name }
}));
}
});
}
});
});
Controller:
public function autoComplete() {
Configure::write('debug', 0);
$this->layout = 'ajax';
$query = $_GET['term'];
$items = $this->Item->find('all', array(
'conditions' => array('Item.name LIKE' => $query . '%'),
'fields' => array('name', 'id', 'category_id'),
'group' => array('name')));
$this->set('items', $items);
}
Form:
<p>
<?php echo $this->Form->create('Item', array('model'=>'item','action' => 'addItem', 'name'=>'AddItem'));?>
<?php echo $this->Form->text('Item.name', array('size'=>'30', 'id'=>'autoComplete', 'autocomplete'=>'off')); ?>
<?php echo $this->Form->text('Item.category_id', array('type'=>'hidden', 'value'=>'0')); ?>
<?php echo $this->Form->text('Groclist.id', array('type'=>'hidden', 'value'=>$groclist['Groclist']['id'])); ?>
<?php echo $this->Form->end('Add'); ?>
</p>
Response:
0: {Item:{name:Cake, id:6, category_id:null}}
1: {Item:{name:Carrot Cake, id:9, category_id:null}}
2: {Item:{name:Carrots, id:8, category_id:null}}
3: {Item:{name:Casserole, id:11, category_id:null}}
4: {Item:{name:Cauliflower, id:10, category_id:null}}
Edited for clarification.
I realize JqueryUI expects label and value and that map should rearrange them, but for some reason it's not. Any ideas?
I found an even better solution. This is done completely in the controller. No view required.
public function autoComplete() {
Configure::write('debug', 0);
*$this->autoRender=false;*
$this->layout = 'ajax';
$query = $_GET['term'];
$items = $this->Item->find('all', array(
'conditions' => array('Item.name LIKE' => $query . '%'),
'fields' => array('name', 'id', 'category_id'),
'group' => array('name')));
*$i=0;
foreach($items as $item){
$response[$i]['value']="'".$item['Item']['id']."'";
$response[$i]['label']="'".$item['Item']['name']."'";
$i++;
}
echo json_encode($response);*
}
What if you reduce the array that is being returned by the Items model. So instead of $this->set('items', $items); you return the json encoded results like so:
foreach($items as $item) {
$data[] = $item['Item'];
}
$data = json_encode($data);
echo $data;
exit;
This is inside the auto_complete method in the controller.
UPDATE:
When querying for Cake for example, it would return a result like so:
[
{"name":"Cake Batter","id":"1","category_id":"3"},
{"name":"Cake Mix","id":"2","category_id":"3"}
]
if you are not wanting to return the json, you could just return $data without the json encoding.
Format Update:
I am not certain if this is to "sloppy", but you could change the foreach loop to:
foreach($items as $item) {
$data[]= array(
'label' => $item['Item']['name'],
'value' => $item['Item']['id']
);
}
Looks like you forgot the Item:
response($.map( data, function( el ) {
return { label: el.Item.id, value: el.Item.name }
});
You can also do it in the server side using Set:
$this->set('items', Set::extract('/Item', $items));
Related
I am using default Yii2 library for auto-complete. How can I make it, so it is reading values from DB while user is typing?
This is code I have so far, but query is done when the page is created:
echo AutoComplete::widget([
'name' => 'tradeName',
'model' => TradeNames::find()->select('name')->all(),
'options' => [
'class' => 'form-control'
],
'clientOptions' => [
'source' => array_column(TradeNames::find()->select('name')->asArray()->all(), 'name'),
},
],
]);
I followed this advice
jqueryui.com/autocomplete/#multiple and have written next code
<div id="autocomplete" class="ui-widget">
<?= \yii\jui\AutoComplete::widget([
'attribute' => 'attribute',
'name' => 'tradeName',
'clientOptions' => [
'source' => \Yii::$container->get('JsExpression',['function(request, response) {
response( $.ui.autocomplete.filter( window.dataAsArray, extractLast( request.term ) ) );
}']),
'select' => \Yii::$container->get('JsExpression',['function(event, ui) {
var terms = split( this.value );
terms.pop();
terms.push( ui.item.value );
terms.push( "" );
this.value = terms.join( ", " );
return false;
}']),
'focus' => \Yii::$container->get('JsExpression',['function() {
return false;
}']),
]
]) ?>
</div>
<script>
window.dataAsArray = ['item1', 'item2', 'item3'];
function split( val ) {
return val.split( /,\s*/ );
}
function extractLast( term ) {
return split( term ).pop();
}
$(document).ready( function() {
$('#autocomplete').on('keydown', function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
});
});
</script>
maybe it help to someone
try this
use yii\jui\AutoComplete;
use yii\web\JsExpression;
<?php
$data = TradeNames::find()
->select(['name as value', 'name as label','id as id'])
->asArray()
->all();
echo 'Trade Names' .'<br>';
echo AutoComplete::widget([
'name' => 'tradeName',
'id' => 'trade_name',
'clientOptions' => [
'source' => $data,
// 'minLength'=>'3',
'autoFill'=>true,
'select' => new JsExpression("function( event, ui ) {
$('#memberssearch-family_name_id').val(ui.item.id);//#memberssearch-family_name_id is the id of hiddenInput.
}")],
]);
?>
<?= Html::activeHiddenInput($model, 'tradeName')?>
Can anyone suggest me how to hide both controller & action name from url in yii2?
I tried by writing rules but did not work.
this is my anchor tag:
<?php echo Html::a($model->title, ['category/view/', 'type' => $model->category->urlValue,'parameter' => $model->urlValue]); ?>
MY current url is like this :
http://localhost/project/category/view/news-and-events/dosarrest-strong-performer-in-2015-forrester-wave-for-ddos-service-providers-1
But I want it like this:
http://localhost/project/news-and-events/dosarrest-strong-performer-in-2015-forrester-wave-for-ddos-service-providers-1
It finally worked by writing a rule in main.php file as follows :
'<type:[A-Za-z0-9-]+>/<param:[A-Za-z0-9 -_.]+>' => 'category/view',
YOu chould create your own UrlRule. Something like:
class CustomUrlRule extends Object implements UrlRuleInterface {
public function createUrl($manager, $route, $params)
{
$parts = explode('/', $r);
if ($route === 'category/view'
&& isset($params['type'])
&& isset($params['parameter'])
) {
$url = generate some url;
unset($params['view'], $params['parameter']);
if (count($params)) {
$url .= '?' . http_build_query($params);
}
return $url;
}
return false;
}
public function parseRequest($manager, $request)
{
//parse request url and return true if it's url for category/view
}
}
and dont forget to add to config
config/web.php:
...
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'app\components\CustomUrlRule',
],
...
],
...
I'm using jQueryUI autocomplete to get a list of cities. I'm using a json array to display cities, but I just can't get the list to appear.
here is my Ajax function :
/**
* #Route("/ajax", name="ajax")
*/
public function ajaxAction(Request $request)
{
$value = $request->get('term');
$em = $this->getDoctrine()->getEntityManager();
$branches = $em->getRepository('AOFVHFlyBundle:City')
->findByName($value);
// Get branches by user if non-admin
$json = array();
foreach ($branches as $branch) {
$json[] = array(
'label' => sprintf('%s (%s)', $branch['name'], $branch['departement']),
'value' => $branch['id']
);
}
$response = new Response();
// better way to return json - via header?
$response->setContent(json_encode($json));
return $response;
}
and here is the form input :
->add('reqdeparture', 'genemu_jqueryautocompleter_entity', array(
'class' => 'AOFVH\FlyBundle\Entity\City',
'property' => 'name',
'route_name' => 'ajax',
'attr' => array(
'placeholder'=>'Départ',
'autocomplete' => 'on')
))
Whatever I type in the input, nothing appears.
Any idea why ? (at first I thought it was because collection was too big, but I barely have 50 cities)
You can use JsonResponse object. The Content-Type header will be 'application/json'. Symfony manage the chars to escape automatically and others conditions to return a JSON normalized correctly.
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* #Route("/ajax", name="ajax")
*/
public function ajaxAction(Request $request)
{
$value = $request->get('term');
$branches = $this->get("doctrine.orm.default_entity_manager")
->getRepository("NamespaceMyBundle:Entity")
->findByName($value);
$json = array();
foreach ($branches as $branch) {
$json[] = array(…);
}
return new JsonResponse($json);
}
Can't seem to figure out what the problem is here. This worked perfectly fine when using 3.5, but does not work with 4.0.
I am using select2.full.js as well which supports using input in this manner.
html:
<input id="vcreate-filter" type="text" name="settings[filter]" class="form-control" style="width:100%;"/>
js:
$("#vcreate-filter").select2({
placeholder: "Select or enter application...",
allowClear: true,
multiple: false,
ajax: {
dataType: 'json',
delay: 1000,
type: 'post',
url: '/process/get_application_list.php',
data: function (term, page) {
return {
term: term, // search term
page_limit: 25, // page size
page: page // page number
};
},
results: function (data, page) {
var more = (page * 25) < data.total; // whether or not there are more results available
return {
results: data.results,
more: more
};
}
},
createSearchChoice:function(term, data) {
if ($(data).filter(function() {
return this.text.localeCompare(term)===0; }).length===0) {
return {id:term, text:term};
}
}
}).on('change', function() {
$(this).valid();
});
get_application_list.php:
.......
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
// make sure there are some results else a null query will be returned
if( count($results) > 0 )
{
foreach( $results as $row )
{
$ajax_result['results'][] = array(
'id' => htmlspecialchars($row['event_target'], ENT_QUOTES, 'UTF-8'),
'text' => htmlspecialchars($row['event_target'], ENT_QUOTES, 'UTF-8')
);
}
}
else
{
// 0 results send a message back to say so.
$ajax_result['results'][] = array(
'id' => 0,
'text' => 'No results found...'
);
}
// return result array to ajax
echo json_encode($ajax_result);
html: use select element instead of input.
<select id="vcreate-filter" type="text" name="settings[filter]" class="form-control" style="width:100%;"> </select>`
js: use processResults instead of 'results' as callback property.
processResults: function (data, page) {
var more = (page * 25) < data.total; // whether or not there are more results available
return {
results: data.results,
more: more
};
}
assuming the json is in the correct format [{"id": "1", "text": "One"}, {"id": "2", "text": "Two"}]
Breaking changes seems to be documented here.
I'am struggling with select2.
I have an ajax call that returns me a json. The json is formated like that (from server):
public function get_groups()
{
$result = array();
$sql = "SELECT * FROM auth_groups ";
foreach ($this->db->query($sql)->result() as $row){
$tmp = array("id" => $row->id ,"label" => $row->name );
array_push($result, $tmp);
}
header('Content-type: application/json');
echo json_encode($result);
}
Then from my javascript i have :
$('#group_choice').select2({
minimumInputLength: 2,
ajax: {
url: "/bonsejour/extranet/ajax/resources/get_groups",
dataType: 'json',
data: function (term, page) {
return {
term:term
};
},
results: function (data, page) {
var results = [];
$.each(data, function(index, item)
{
results.push({id:item.ID, text:item.label});
});
return {
results: results
};
}
}
});
Where #group_choice is an input text.
When i type some text inside the input box it does shows all the elements coming from the json. But when i try to select an element nothing happens. How can i select the elements inside the input ?
Thanks
Refer http://ivaynberg.github.io/select2/#documentation
formatSelection: formatSelectionMethod,
function formatSelectionMethod(row) { return row.text;}
I hope you will find it helpful.
Please refer to Select2 Ajax Method Not Selecting,
and take the correct value:
id: function(data){return {id: data.id};},
or
id: function(data){return data.id}