LoginSignup
6
4

More than 5 years have passed since last update.

Flaskでflexdatalistを使ってオートコンプリート機能を実装

Last updated at Posted at 2018-07-28

webアプリケーションのフォームで、予期せぬ値を入力できないようにしたくて、今回は、jQueryのライブラリであるflexdatalistを使って、オートコンプリート機能によって、入力値に制限を加える実装をしてみました。

他にも、バリデーションを厳しくかけたり、フォーム送信後に整形したりすることもありますが、今回は、オートコンプリート!

demo.mov.gif

もくじ

  • flexdatalistでカンタンなデモアプリを作ってみる
  • Flaskのフォームでflexdatalistを使ってみる

flexdatalistでカンタンなデモアプリを作ってみる

Flaskに導入する前に、flexdatalistだけで超簡単なデモを作ってみます。

flexdatalistって何?

  • flexdatalist 公式ドキュメント
  • JQueryのライブラリ
  • 「mutiple values」を使えば、複数の値をカンマ区切りで送信できる。 (← 今回はこれ使った)

ライブラリの読み込み

まず、ライブラリの読み込みから丁寧目にやります。

  • index.htmlを作る
  • 公式ドキュメントの下部にある「HOW TO INSTALL」をもとに、headの中に必要な情報を記入していきます。
  • ドキュメント上部にあるDownloadボタンから、必要なファイルをlocalに置きます。
    • js/libディレクトリを作って、その下にとりあえず置いておきます。(下の方に最終的なディレクトリ構造を載せてあります。)

(久しぶりに、jQueryを触って、いろいろ忘れていたから、じっくりと。)

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flexdatalist Sample</title>
    <script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
    <link href="js/lib/jquery-flexdatalist-2.2.4/jquery.flexdatalist.min.css" rel="stylesheet" type="text/css">
    <script src="js/lib/jquery-flexdatalist-2.2.4/jquery.flexdatalist.min.js"></script>
</head>
<body>
</body>
</html> 

デモアプリ実装

とりあえず、index.htmlのbodyタグの中に、下記をベタ書きしていきます。

  • 入力欄
  • オートコンプリートで入力させたい文字列リスト
  • jsの関数
index.html
<body>

<input type='text'
       class='flexdatalist'
       data-min-length='1'
       multiple='multiple'
       list='drink_list'
       name='drink_list'>

<datalist id="drinki_list">
    <option value="Late">Late</option>
    <option value="Mocha">Mocha</option>
    <option value="Cappuccino">Cappuccino</option>
    <option value="Blend">Blend</option>
    <option value="Espresso">Espresso</option>
    <option value="Lemonade">Lemonade</option>
    <option value="Chai">Chai</option>
    <option value="Cold Brew">Cold Brew</option>
    <option value="Single Origin Espresso">Single Origin Espresso</option>
    <option value="Gibraltar">Gibraltar</option>
</datalist>

<script>
    $('.flexdatalist').flexdatalist({
     minLength: 1
    });
</script>

</body>

ブラウザで開いて、正常に動くか確かめてみましょう。
(WebStormとか、PyCharmを使っていたら、index.htmlを右クリックで、「Open in Browser」でカンタン。)

ハマったところ

  • minLength
    • inputタグの中とscriptのjsの中で指定することができる。
    • だが、反映される優先順位が高いのは、inputタグの中。
    • jsの方で minLength: 100 とかにしても、inputタグの data-min-length='1' が優先され、1文字入力すれば検索をしてくれる。

Flaskのフォームでflexdatalistを使ってみる

上で一通り作ったflexdatalistを、Flaskのフォームに適応させていきます。

Flaskのフォームを作る

まずは、適当にFlaskでフォームを作ってみます。

app.py
from flask import Flask, render_template, request, redirect
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.config["SECRET_KEY"] = 'coffee drinker' #CSRF対策で必要らしい

class Form(FlaskForm):
    drink_list = StringField("drink_list", validators=[])

@app.route("/", methods=["GET", "POST"])
def index():
    form = Form()

    return render_template("index.html", form=form)

@app.route("/submit", methods=["POST"])
def submit():
    form = Form()

    if form.validate():
        drink_names = request.form["drink_list"]

        return render_template("result.html", drink_name=drink_names)

    return render_template("index.html", form=form)

if __name__ == "__main__":
    app.run(debug=True)

flexdatalistにFlaskを適用してみる

先程作ったindex.htmlをFlask対応させた記述に変更します。
ついでに、htmlファイルにあったjsの記述は、新しくjsファイルを作って、そちらに移動させましょう。

ディレクトリの移動

まず、htmlファイルやjsファイルは、Flaskで決まっている位置に置きましょう。

ちなみに、ディレクトリ構造はこんな感じにしてあります。

flask-auto-complete
   ├── app.py
   ├── static
   │   ├── drink_list.json
   │   └── js
   │       ├── lib
   │       │   └── jquery-flexdatalist-2.2.4
   │       │       ├── LICENSE
   │       │       ├── README.md
   │       │       ├── bower.json
   │       │       ├── jquery.flexdatalist.css
   │       │       ├── jquery.flexdatalist.js
   │       │       ├── jquery.flexdatalist.min.css
   │       │       ├── jquery.flexdatalist.min.js
   │       │       └── package.json
   │       └── script.js
   └── templates
       ├── index.html
       └── result.html

※ script.js, drink_list.json, result.htmlは後で作る。

それに伴い、ファイル内のファイルパスの指定も url_for を使って書き直しましょう。

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>flexdatalist Sample</title>
    <script src="https://code.jquery.com/jquery-3.3.1.js" integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=" crossorigin="anonymous"></script>
    <link href="{{ url_for('static', filename='js/lib/jquery-flexdatalist-2.2.4/jquery.flexdatalist.min.css') }}" rel="stylesheet" type="text/css">
    <script src="{{ url_for('static', filename='js/lib/jquery-flexdatalist-2.2.4/jquery.flexdatalist.min.js') }}"></script>
</head>

<body>
<form method="POST" action="/submit">
    {{ form.hidden_tag() }}
    <input type='text'
           class='flexdatalist'
           data-data="{{ url_for('static', filename='drink_list.json')}}"
           name='drink_list'>
    <input type="submit" value="Send">
</form>
<script src="{{ url_for('static', filename='js/script.js') }}"></script>

jsファイルへ移行

script.js
$('.flexdatalist').flexdatalist({
    minLength: 1,
    searchIn: 'name',
    data: "{{ url_for('static', filename='drink_list.json') }}",
    selectionRequired: true,
    multiple: true
});

drink_listをjsonファイルに切り出す

htmlファイルにべた書きしておくと、単純にダサいですし、量が増えたときに見づらくなるので、切り出して別ファイルに置いておきます。

drink_list.json
[
    {"name": "Late"},
    {"name": "Mocha"},
    {"name": "Cappuccino"},
    {"name": "Blend"},
    {"name": "Espresso"},
    {"name": "Lemonade"},
    {"name": "Chai"},
    {"name": "Cold Brew"},
    {"name": "Single Origin Espresso"},
    {"name": "Gibraltar"}
]

フォーム送信後のページを作成

せっかくなので、フォームを送信後のページを、入力した値を使って表示させました。

result.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Result</title>
</head>
<body>
 <h2>{{ drink_name }} 美味しかった!!!</h2>
 </body>
</html>

このコマンドをターミナルで打つか、PyCharmで実行して、ブラウザにlocalhost:XXXXで、正しく動くか確認しましょう。

$ python app.py

終わりに

僕の力不足で、理解しづらい点もあったかもしれませんが、無事、実装できましたか?

GitHubに開発の流れでコミットしてるので、是非参考にしてください。
また、編集リクエストもお待ちしています。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4