CakePHP Javascript,jQuery

CakePHP2 + jQueryUIでテキストボックスにオートコンプリート(オートサジェスト)機能をつける方法

2018/09/11

テキストボックスにオートコンプリート(オートサジェスト)機能を、CakePHP2 + jQuery UI 環境で作成したので作り方を備忘録としてポストします。

jQuery UI でオートコンプリートする方法【単純編】

基本的な作り方

まずは基本の方法。CakePHP2(データベース)を使わずに作ってみます。

jQuery UI の読み込み

jQuery を先に読んで、次に jQuery UI を読み込みます。

[html]


[/html]

ビューでテキストボックスの用意

ID名もしくはclass名を付与。
今回は id ですが、class でも問題なし。

[html]

[/html]

サジェスト内容の準備、抽出

サジェスト候補のマスタ配列(例:availableTags)を用意し、対象のテキストボックスに対してオートコンプリート機能を割り当てています。

ページ読み込みと同時に作動させるために、
$(function() {}
内へ必要なスクリプトを書き込みます。

[html]

[/html]

代表的なオプション

パラメータ 概要 備考/初期値
source 型:Array or String or Function(Object request, Function response(Object data))
初期値:無し(入力必須)

候補リストを定義

必須
autoFocus 型:Boolean
リスト表示に際してリストの1番目にするかを指定
false
delay 型:Integer
キー入力からリスト表示までの遅延時間(ミリ秒)
300
disabled 型:Boolean
オートコンプリートを無効化するかを指定
false
minLength オートコンプリート機能が働く最小文字数 1

デモ

デモはコチラから。

軽い解説

先にサジェスト候補内容を作成し、それらをフォームに対して割り当てているだけです。
かなり簡単ですね。

コチラを利用する場合は先頭の文字から始まるものを候補として出すのではなく、1個のワード内に含まれる文字を探り当てて候補としてくれます。

具体的には、"a"と入れた場合、

  • ActionScript
  • AppleScript
  • Asp
  • BASIC
  • Erlang
  • Fortran
  • Haskell
  • Java
  • JavaScript
  • Scala

"o"と入れた場合、

  • ActionScript
  • Clojure
  • COBOL
  • ColdFusion
  • Fortran
  • Groovy
  • Python

が候補として上がります。

CakePHPでサジェスト内容を作成する

ということで予想はつきますが、先に用意するサジェスト部分をデータベースから取得すれば簡単に出来そうです。
適当に以下の様なものを作ります。

コントローラー(TestsController)

最終的に、JSONデータに変換しています。

[php]
public function form()
{
$conditions = array(
'NOT' => array(
'OR' => array(
'Test.word' => NULL,
'Test.word' => '',
)
),
'AND' => array(
'Test.publish' => 1,
)
);
$fields = array('Test.id', 'Test.word');

$suggestWordArray = $this->Test->find( 'list',
array(
'conditions' => $conditions,
'fields' => $fields,
'recursive' => -1,
'order' => $order,
)
);

// 重複を削除し、要素番号(キー)を0から振り直す
$data = array_values(array_unique($suggestWordArray));

$suggestWordJson = json_encode($data); // 配列をJsonデータへ変換
$this->set('suggestWordJson', $suggestWordJson);
}
[/php]

ビュー(/tests/form.ctp)

先ほどの、「availableTags」配列内容部分をPHPの出力にするだけ。
お手軽。

[html]

[/html]

先頭文字で語句を指定、作成したい場合【応用1】

やってみたかったこと

先の場合、"a"を入れた場合、「語句に"a"が含まれるもの」を候補として上がっていましたが、「"a"から始まるもの」を候補として上げたい場合の方法です。

サジェスト内容の作成、抽出

ビュー(/tests/form.ctp)

[html]

[/html]

適当なコントローラーとアクションを作成し、URLで指定。これで、$_GET['term'] で指定URLにパラメータを渡せます。
そのパラメータを利用してサジェスト候補を作成すれば良いだけです。

コントローラー(TestsController)

[php]
public function autoSuggest2()
{
$term = $this->params['url']['term'];

$conditions = array(
'NOT' => array(
'OR' => array(
'Test.word' => NULL,
'Test.word' => '',
)
),
'AND' => array(
'Test.publish' => 1,
)
);
$fields = array('Test.id', 'Test.word');

$suggestWordArray = $this->Test->find( 'list',
array(
'conditions' => $conditions,
'fields' => $fields,
'recursive' => -1,
'order' => $order,
)
);

// サジェスト候補の作成
$data = array();
if (!empty($term)) {
foreach ($suggestWordArray as $word) {
$position = strpos(strtolower($word), strtolower($term));

if ($position !== false && $position == 0) {
$data[] = $word;
}
}
} else {
$data = $suggestWordArray;
}

echo json_encode($data);
}
[/php]

結果

"a"と入れた場合、

  • ActionScript
  • AppleScript
  • Asp

"o"と入れた場合は候補は表示されず、という感じです。
若干、レスポンスは遅いのですが、ほしい形になりました。

正直、採用するかどうかは微妙なところ。

CakePHPのAJAXを使って、ややこしくしてみた【応用2】

インプットに入力された文字からリアルタイムでSQL作成、候補として出力する方法を考えてみました。
最終的には採用しませんでしたが、いつか役に立つかも知れない備忘録なので載っけておきます。

ビュー

対象のフォームに対する keyup に bind する形のコードを書きます。

[html]

[/html]

コントローラ(TestController)

最終的にJSON形式にして出力しています。

[php]
public function autoSuggest()
{
$this->layout = false;
$this->autoRender = false;
$data = '';
$json = '';

// Ajax以外の通信の場合
if (!$this->request->is('ajax')) {
throw new BadRequestException();
}

if (!empty($this->params['url']['query'])) {
$options = array(
'fields' => array('Test.id', 'Test.word'),
'conditions' => array(
'OR' => array(
'Test.word LIKE' => $this->params['url']['query'] . '%'
),
),
'limit' => 20
);

$datas = $this->Test->find('list', $options);
$data = array_values(array_unique($datas));
}

$json = json_encode($data); // Json形式に

return $json;
}
[/php]

これで、テキストボックスに語句を入力するたびに、SQLを作成し、候補を出力するようになりました。
CakePHP2 + AJAX がよくわかっていない上に、これも微妙にレスポンスが悪く、採用は見送りました。

多分、もっと良い方法がいろいろとあると思うのですが、今回はここまでということで。

参考にしたサイト様

-CakePHP, Javascript,jQuery
-, , , , , , , , ,