質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.20%

ajaxで入力チェックを併用する場合の実務

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,432

SugiuraY

score 249

夜分失礼いたします。

下記のように、クライアントサイドで入力チェックを作成しているのですが、#erのユーザ名がすでに使用されているかどうかというチェック項目のみ非同期通信で、サーバー処理をさせています。このような処理の構造自体はよくあると思います。

<div class="register_wrapper">
     <div class="flex_inner flex_right">
        <input type="text" id="username" class="register_text" placeholder="ユーザ名"/>

        <select name="select_1" id="" style="font-size:13px;" class="ui dropdown">
            <option class="gender" value="">性別</option>
            <option class="gender" value="1">女性</option>
            <option class="gender" value="2">男性</option>
        </select>
     </div>

  </div>
<button class="register_button" type="button">アカウントを作成する</button>
$(document).on('click','.register_button',function(){
  $('#er1,#er2,#er3').remove();
  const username = $('#username').val();
  const gender = $('.gender:selected').val();


/*未入力チェック*/
  const errCode = [];
  if (username=="") {
    errCode.push("username")
  }else{
    errCode.splice(errCode.indexOf("username"),1);
  }
  if (gender=="") {
    errCode.push("gender")
  }else{
    errCode.splice(errCode.indexOf("gender"),1);
  }

                $.ajax({
                  type:'POST',
                  url:'duplicatename.php',
                  datatype:'json',
                  data:{
                    transfer_name:username
                  }
                 })
                 .then(
                   function(data){//success
                       if (data.status) {
                       errCode.push("usedname")
                       $('<p id="er3" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbspすでに使用されているユーザ名です</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
                     }else{
                       errCode.splice(errCode.indexOf("usedname"),1);
                     }
                   },
                   function(){//fail
                     console.log('failed');
                   }
                 )

//error message
    if (errCode.indexOf("username")>=0) {
      $('<p id="er1" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbspユーザ名を入力してください</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
    }
    if (errCode.indexOf("gender")>=0) {
    $('<p id="er2" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbsp性別を選択してください</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
    }


 })

本来は名前の重複である#er3も含めて、errCodeに格納して、最終的に配列に何かのエラーがあれば、
それぞれに対応するエラーを吐き出すとしたいのですが、当然非同期でやっている#er3については、"usedname"が格納されることをまたずにifでエラーの有無判定が実行されているため、現在、上記のようにajax内で分けて処理させております。

  if (errCode.indexOf("usedname")>=0) {
      $('<p id="er3" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbspすでに使用されているユーザ名です</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
    }

上記のような処理にした結果、errormessgeのappendToのタイミングも微妙にずれてくるので気持ちが悪いのですが、一般的にこのようにクライアントサイドとajaxを使ったサーバーサイドのチェックを併用する場合

1) 他のエラー(#er1や#er2)も、下記のようにajax内の処理に含めて実行するのでしょうか?
2) それとも他の解決方法があり一般的なものがあればご教示頂けますでしょうか?

 .then(
    function(data){//success
        const errCode = [];
        if (username=="") {
            errCode.push("username")
        }else{
            errCode.splice(errCode.indexOf("username"),1);
        }
        if (gender=="") {
            errCode.push("gender")
        }else{
            errCode.splice(errCode.indexOf("gender"),1);
        }
        if (data.status) {
            errCode.push("usedname")
        }else{
            errCode.splice(errCode.indexOf("usedname"),1);
        }

        if (errCode.indexOf("username")>=0) {
        $('<p id="er1" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbspユーザ名を入力してください</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
        }
        if (errCode.indexOf("gender")>=0) {
        $('<p id="er2" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbsp性別を選択してください</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
        }
        if (errCode.indexOf("usedname")>=0) {
        $('<p id="er3" class="errmessage"><i class="fa fa-exclamation-circle" aria-hidden="true"></i>&nbspすでに使用されているユーザ名です</p>').appendTo('.errmessagebox').hide().fadeIn(1000);
        }
        if (errCode.length<1){
        /*エラーがない場合の処理を実行*/
        }
    },
    function(){//fail
      console.log('failed');
    }
)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

質問文中にある方法(サーバー検証の結果が返ってきたときに、クライアント検証を行う)で、問題ないと思います。

ただ、もしクライアント検証とサーバー検証が同等の処理でない(サーバー検証→クライアント検証の順で行う必要がある)ことを気にするなら、クライアント検証を一瞬で終わる非同期処理とみなして、検証処理すれば良いかと思います。

//クライアント検証
var clientValidate = function(){
  var def = $.Deferred();
  const errCode = [];
  if (username=="") {
    errCode.push("username")
  }else{
    errCode.splice(errCode.indexOf("username"),1);
  }
  if (gender=="") {
    errCode.push("gender")
  }else{
    errCode.splice(errCode.indexOf("gender"),1);
  }
  return def.resolve(errCode).promise();
};

//サーバー検証
var serverValidate = function(){
  return $.ajax({
    type:'POST',
    url:'duplicatename.php',
    datatype:'json',
    data:{
      transfer_name:username
    }
  });
};

//各検証の実行
const p1 = clientValidate();
const p2 = serverValidate();

//クライアント検証・サーバー検証の両方の処理が終わったあとに
//検証後の処理を実行する
$.when(p1, p2).done(function(result1, result2){
    //処理続行 or エラー表示
});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/30 23:07

    コメントありがとうございます、
    自分自身で長文を書いたので、申し訳ないのですが、文中にある方法とは、thenでsuccess時にすべての処理を記載する方法を指していると理解いたしました。

    deferred when promiseの存在は知っていたのですが、このような使い方なんですね!!

    "クライアント検証を一瞬で終わる非同期処理とみなして"という点がまだ理解ができないのですが、この機会にこれらの使い方を勉強してみようと思います!

    キャンセル

  • 2018/10/30 23:21

    >文中にある方法とは、thenでsuccess時にすべての処理を記載する方法を指していると理解いたしました。
    言葉足らずで申し訳ありません。「文中にある方法」は、仰るとおりです。

    >"クライアント検証を一瞬で終わる非同期処理とみなして"という点がまだ理解ができないのですが
    こちらも言葉足らずですみません。$.ajax()の戻り値はPromiseなので、clientValidateのように、同期検証の戻り値もPromiseにすると、同期検証の結果を非同期検証の結果と同じように扱うことができるようになるという意味で書きました。

    キャンセル

  • 2018/10/31 00:13

    コメントいただきありがとうございます。
    とんでもございません、こちらこそ理解不足で申し訳ございません。
    概ね理解することができました!細かい仕様は自分自身でも勉強して早速実装してみようと思います。
    質問して本当に良かったです。
    改めて深謝を申しあげます。
    よろしくお願い申し上げます。

    キャンセル

+1

単にその非同期処理が終わるのを待って、エラー有無判定をすればいいだけですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/30 23:00

    コメントありがとうございます。
    初心者のため、思い切ってお尋ねさせてください。
    ajaxでは非同期処理が終わってから処理するのは、successの中に(上記ではthen)のなかに処理を記述するほかないと理解しているのですが、ほかに方法があるのでしょうか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.20%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる