HTMLフォームの読み取り専用SELECTタグ/入力


587

HTML仕様によると、HTMLのselectタグにはreadonly属性がなく、disabled属性のみがあります。したがって、ユーザーがドロップダウンを変更できないようにするには、を使用する必要がありますdisabled

唯一の問題は、無効化されたHTMLフォーム入力がPOST / GETデータに含まれないことです。

タグのreadonly属性をエミュレートし、selectそれでもPOSTデータを取得する最良の方法は何ですか?


5
サーバー側ではこれに依存しないでください。誰でも独自のHTMLページを作成してRWにすることができます。
ブレンダンバード

11
しかし、これはPHP固有の問題ではありません。
Kaleb Brasee 2013年

4
この場合、select要素をまったく使用しないことをお勧めします。値をプレーンテキストとして表示できない理由はありますか?
Big McLargeHuge 14

2
@ppumkinコメントは意味がありません。選択または非表示のフォームフィールドの良いユースケースは決してないと言っているのではありません。OPがページにテキストを表示するのに問題があり、この場合にselect要素を使用する目的が何であるかを単に疑問に思っていました。
Big McLargeHuge 2014年

2
私は間違った質問を読んでいるに違いありません。ユーザーが変更しないように、選択を無効にしたいと彼は言います。多分彼は変更を防ぐために、selectでページをレンダリングし、jqueryを使用する必要があります。しかし、彼がそれを提出すると、そのデータはありません。私も同じことをしていました。他の選択によってフィルタリングされた選択を表示する必要があり、最後のドロップダウンはajax経由でDBに保存するため、前のすべてをロックダウンする必要があります。ページを再表示するとき、ええ、OK-選択の代わりにラベルを表示できました。しかし、それは問題ではありません:)
Piotr Kula 14年

回答:


461

select要素を保持するdisabledだけでなくinput、同じ名前と値を持つ非表示の要素を追加する必要があります。

SELECTを再度有効にする場合は、その値をonchangeイベントの非表示入力にコピーし、非表示入力を無効にする(または削除する)必要があります。

ここにデモがあります:

$('#mainform').submit(function() {
    $('#formdata_container').show();
    $('#formdata').html($(this).serialize());
    return false;
});

$('#enableselect').click(function() {
    $('#mainform input[name=animal]')
        .attr("disabled", true);
    
    $('#animal-select')
        .attr('disabled', false)
    	.attr('name', 'animal');
    
    $('#enableselect').hide();
    return false;
});
#formdata_container {
    padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
    <form id="mainform">
        <select id="animal-select" disabled="true">
            <option value="cat" selected>Cat</option>
            <option value="dog">Dog</option>
            <option value="hamster">Hamster</option>
        </select>
        <input type="hidden" name="animal" value="cat"/>
        <button id="enableselect">Enable</button>
        
        <select name="color">
            <option value="blue" selected>Blue</option>
            <option value="green">Green</option>
            <option value="red">Red</option>
        </select>

        <input type="submit"/>
    </form>
</div>

<div id="formdata_container" style="display:none">
    <div>Submitted data:</div>
    <div id="formdata">
    </div>
</div>


5
選択を再度有効にする場合は、もちろん、(説明に従って値をコピーした後)非表示の入力を無効にするか削除する必要があります。それ以外の場合は、送信された値が2倍になります
Adam

1
@max Ah !. わかりました。隠し入力には、selectに名前が付いていた「同じ名前」が必要だと言ったので、
アダム

2
複数選択を使用している場合はどうなりますか?
Anyul Rivas 2013

2
同じ名前の2つの要素があると、最後に有効化された入力/選択されたものだけがポストバックされ、ダブルはポストバックされません。また、selectedリスト全体ではなく、値のみがポストバックされます。したがって、あなたのhidden前に座っselectて、選択した値を保持します。「読み取り専用」で選択が無効になると、ポストバックには非表示の入力の値のみが含まれます。選択が有効になっている場合、表示されている選択オプションは非表示の値を「上書き/置換」し、それがポストバックされる値です。
Piotr Kula 2014年

29
これは明白な解決策ですが、別の入力フィールドを追加する必要があるため、解決策としてはうんざりです。
Donato

189

これも使えます

選択したオプションを除くすべてを無効にします。

<select>
    <option disabled>1</option>
    <option selected>2</option>
    <option disabled>3</option>
</select>

このようにして、ドロップダウンは機能します(その値を送信します)が、ユーザーは別の値を選択できません。

デモ


3
動的オプションに
最適

11
単一値のSELECTタグに最適です!ただし、<複数選択>では機能しません。これにより、ユーザーは選択したオプションの一部を選択解除して、値を変更できます。
ミハイルバンキン、2015年

2
optionタグのdisabled属性に対するブラウザのサポート
Jo。

4
これは素晴らしいソリューションです。:私はあなたがこのようにjQueryを使って簡単にそれを達成することができることを追加します $("#yourSelectId option:not(:selected)).attr("disabled", "disabled")
Onkel-jの

105

送信時に選択オブジェクトを再度有効にすることができます。

編集:つまり、通常はselectタグを無効にし(disabled属性を使用)、フォームを送信する直前に自動的に再度有効にします。

jQueryの例:

  • それを無効にするには:

    $('#yourSelect').prop('disabled', true);
  • GET / POSTデータが含まれるようにサブミットする前に再度有効にするには:

    $('#yourForm').on('submit', function() {
        $('#yourSelect').prop('disabled', false);
    });

さらに、無効になっているすべての入力を再度有効にするか、以下を選択できます。

$('#yourForm').on('submit', function() {
    $('input, select').prop('disabled', false);
});

4
.prop( 'disabled'、true / false)を使用して、disabledプロパティを設定します。属性は実際の状態を変更しません。
パリチャー

このソリューションは@bezmaxソリューションよりも賢いと思います。非表示の入力を追加する場合、各入力(同じ名前)のいずれか1つのみが常に有効になることを考慮する必要があったためです。それ以外の場合、両方の入力が有効になっていると、サーバー側で、プログラムが例外の原因となる可能性のある入力の配列を取得します(たとえば、この状況を処理せず、1つの文字列を期待して 'Request.Form [FieldName]を使用する場合'コマンド)
MiT 2015年

@ Kevin、90%以上のケースで機能します。また、あなたはあなたのベルトにjqueryを持っている必要があります...ええ。
2016年

これは受け入れられた答えをはるかにきれいにします。要素を無効にしたくない場合や追加の入力タグがない場合は、ロジックを元に戻すのが簡単です。
Haohmaru 2016

51

要素にreadOnly属性を設定する別の方法selectは、css

あなたは次のようにすることができます:

$('#selection').css('pointer-events','none');

デモ


8
素晴らしい解決策。ただし、値はキーボードで変更できます。
Mario Werner

1
ええ、これはかなり素晴らしいです。キーボードで値を変更するには、Tabキーを押して要素に移動すると、要素が選択されます。背景色を灰色または無効にすると、実際には無効になっていないのに、これが「無効」であることをユーザーに視覚的に通知することもできます。もはや誰もIEをサポートしていません。防止したい場合は、キーダウン防止のデフォルトを設定することもできます。
Piotr Kula 2014年

正統派じゃない!! selectをページレンダリングからブロックする必要がある場合... .on('mouseover', function(){ ... });
Fr0zenFyr

pointer-events: noneマウスカーソルからのフォーカスを防ぎます。また、キーボードからフォーカスを防ぐために、あなたはすべてのフォーカスイベント直後にぼかしてそれを補完することができます:$('select').css('pointer-events', 'none').on('focus', function () {$(this).blur();});
クインComendant

39
<select id="countries" onfocus="this.defaultIndex=this.selectedIndex;" onchange="this.selectedIndex=this.defaultIndex;">
<option value="1">Country1</option>
<option value="2">Country2</option>
<option value="3">Country3</option>
<option value="4">Country4</option>
<option value="5">Country5</option>
<option value="6">Country6</option>
<option value="7" selected="selected">Country7</option>
<option value="8">Country8</option>
<option value="9">Country9</option>
</select>

WindowsおよびGoogle Chrome用のIE 6、7および8b2、Firefox 2および3、Opera 9.62、Safari 3.2.1でテストおよび動作。


15
これの問題は、ドロップダウンが読み取り専用ではないかのようにレンダリングされることです。ユーザーは物事がうまくいかないと思います...
Lukas Eder

8
ユーザーはオプションを選択できるため、これはユーザーを混乱させますが、ユーザーがオプションを選択すると、リストは以前に選択した値に戻ります。ユーザーが何も選択できないようにリストを無効にする方がはるかに直感的です。
dana

11
同様の問題があり、選択したオプションのみを表示して解決しました。JSは不要で、ユーザーの混乱が少なくなります... <select id="countries"> <option value="7" selected="selected">Country7</option> </select>
Potherca

1
@ppumkin @dana @LukasEderいいえ。このUXを修正できる場合はそうではありません。たとえば、次のような何かを行うことができますonchange = 'this.selectedIndex=this.defaultIndex; alert("You should not change this..");'。..だけではなく、静かに選択されたインデックスを変更する
Fr0zenFyr

1
@LukasEder回答者の体験に熱心な人は誰でも、CSSを追加して、ドロップダウンを変更しないことを本当に強調できます。カーソルをnot-allowedに、背景色をに設定します#CCC
Alexander Dixon

36

シンプルなjQueryソリューション

選択にreadonlyクラスがある場合は、これを使用します

jQuery('select.readonly option:not(:selected)').attr('disabled',true);

または、selectにreadonly="readonly"属性がある場合

$('select[readonly="readonly"] option:not(:selected)').attr('disabled',true);

7
コードについて少し説明してください。select要素に「読み取り専用」クラスを追加する必要がありますか?いつこのコードを呼び出す必要がありますか?document.readyのみで、または選択が有効/無効になるたびに?あなたのコードはスクリプトが安全ですか?
anar khalilov 2014年

$(document).ready(function(){$('select option:not(:selected)').attr('disabled',true);});単一選択で問題なく動作します。「読み取り専用」クラスは必要ありません。複数選択は、すでに複数のオプションが選択されていて無効になっておらず、ユーザーが無効になっていないオプションの1つを選択すると、以前に選択されていた他のオプションが選択解除されるという問題があります。
ゴードン

これを理解できません。
Piotr Kula 2014年

「読み取り専用」クラスの選択ボックスでは、選択したオプション以外のオプションを無効にします。あなたが手にselect要素を持っている場合は、書くことができます:$select.find('option').not(':selected').attr('disabled', 'disabled');
Semra

1
私はこのソリューションが好きです。セレクターをに変更しselect[readonly]て、要素にreadonly属性を追加するだけにします。これにより、他のタイプとは異なる方法で選択を処理する必要がなくなります。次に、JavaScriptは効果を徐々に高めます。このソリューション(および他のほとんどのソリューション)は、ユーザーエージェントが最高のユーザーエクスペリエンスを提供するのに役立つだけであり、実際には何も強制しません(必要に応じてサーバー側で実行する必要があります)。
jgivoni

21

シンプルなCSSソリューション:

select[readonly]{
    background: #eee;
    cursor:no-drop;
}

select[readonly] option{
    display:none;
}

これにより、選択が灰色になり、カーソルを合わせたときに「無効」カーソルが表示され
、選択時にオプションのリストが「空」になるため、値を変更できません。


1
(symfonyや他の多くのフレームワークのように)CSRF検証がある場合、それは機能しません。
ThEBiShOp 2017


11

これは私が見つけた最良の解決策です:

$("#YourSELECTIdHere option:not(:selected)").prop("disabled", true);

上記のコードは、選択されたオプションを有効にしたまま、選択されていない他のすべてのオプションを無効にします。選択したオプションを選択すると、ポストバックデータになります。


11

遅すぎることはわかっていますが、簡単なCSSで実現できます。

select[readonly] option, select[readonly] optgroup {
    display: none;
}

選択readonly状態のとき、スタイルはすべてのオプションとグループを非表示にするため、ユーザーは選択を変更できません。

JavaScriptハックは必要ありません。


素敵でシンプル。私はそれが好きです。
Jonathan

これは問題に対する非常に優れた解決策です。ありがとうございました!
OderWat

10

さらに簡単:スタイル属性を選択タグに追加します。

style="pointer-events: none;"

私にとってはその仕事ですが、ポインターイベントはクロスブラウザーをサポートしますか?
Abhijit Jagtap

3
うまくいきません。ユーザーはキーボードを使用して入力を変更できます。
Sandhu

6

これが最も簡単で最良のソリューションです。selectまたはread-nyのような他のattrにreadolny属性を設定し、次のようにします。

$("select[readonly]").live("focus mousedown mouseup click",function(e){
    e.preventDefault();
    e.stopPropagation();
});

1
ここにキーアップ広告キーダウンを追加する必要があります。また、ドロップダウンに「タブ」で移動し、矢印キーを使用して値を変更することもできます。
apfz 2017

5

読み取り専用にする予定の場合は、選択を無効に設定し、フォームを送信する直前に無効属性を削除します。

// global variable to store original event/handler for save button
var form_save_button_func = null;

// function to get jQuery object for save button
function get_form_button_by_id(button_id) {
    return jQuery("input[type=button]#"+button_id);
}

// alter value of disabled element
function set_disabled_elem_value(elem_id, value)  {
    jQuery("#"+elem_id).removeAttr("disabled");
    jQuery("#"+elem_id).val(value);
    jQuery("#"+elem_id).attr('disabled','disabled');
}

function set_form_bottom_button_save_custom_code_generic(msg) {
    // save original event/handler that was either declared
    // through javascript or html onclick attribute
    // in a global variable
    form_save_button_func = get_form_button_by_id('BtnSave').prop('onclick'); // jQuery 1.6
    //form_save_button_func = get_form_button_by_id('BtnSave').prop('onclick'); // jQuery 1.7

    // unbind original event/handler (can use any of following statements below)
    get_form_button_by_value('BtnSave').unbind('click');
    get_form_button_by_value('BtnSave').removeAttr('onclick');

    // alternate save code which also calls original event/handler stored in global variable
    get_form_button_by_value('BtnSave').click(function(event){
        event.preventDefault();
        var confirm_result = confirm(msg);
        if (confirm_result) {
            if (jQuery("form.anyForm").find('input[type=text], textarea, select').filter(".disabled-form-elem").length > 0) {
                jQuery("form.anyForm").find('input[type=text], textarea, select').filter(".disabled-form-elem").removeAttr("disabled");
            }

            // disallow further editing of fields once save operation is underway
            // by making them readonly
            // you can also disallow form editing by showing a large transparent
            // div over form such as loading animation with "Saving" message text
            jQuery("form.anyForm").find('input[type=text], textarea, select').attr('ReadOnly','True');

            // now execute original event/handler
            form_save_button_func();
        }
    });
}

$(document).ready(function() {
    // if you want to define save button code in javascript then define it now

    // code below for record update
    set_form_bottom_button_save_custom_code_generic("Do you really want to update this record?");
    // code below for new record
    //set_form_bottom_button_save_custom_code_generic("Do you really want to create this new record?");

    // start disabling elements on form load by also adding a class to identify disabled elements
    jQuery("input[type=text]#phone").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("input[type=text]#fax").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("select#country").addClass('disabled-form-elem').attr('disabled','disabled');
    jQuery("textarea#address").addClass('disabled-form-elem').attr('disabled','disabled');

    set_disabled_elem_value('phone', '123121231');
    set_disabled_elem_value('fax', '123123123');
    set_disabled_elem_value('country', 'Pakistan');
    set_disabled_elem_value('address', 'address');

}); // end of $(document).ready function

それは起こるのを待っている競争状態のように聞こえます。
ブレンダンバード

5

選択可能でないはずのオプションを無効にすることに加えて、実際にリストからそれらを表示させないようにしましたが、後で必要になった場合でも有効にすることができます。

$("select[readonly]").find("option:not(:selected)").hide().attr("disabled",true);

これにより、読み取り専用属性を持つすべての選択要素が検索され、選択されていない選択内のすべてのオプションが検索され、非表示にされて無効になります。

jqueryはコードを右から左に読み取るため、パフォーマンス上の理由からjqueryクエリを2つに分離することが重要です。コード:

$("select[readonly] option:not(:selected)")

最初にドキュメント内の選択されていないすべてのオプションを検索し、select内にあるオプションを読み取り専用属性でフィルタリングします。


たぶん.prop("disabled", true)代わりに
sam

4

簡単なサーバー側のアプローチの1つは、選択するオプション以外のすべてのオプションを削除することです。したがって、Zend Framework 1.12では、$ elementがZend_Form_Element_Selectの場合:

 $value =  $element->getValue();
 $options = $element->getAttrib('options');
 $sole_option = array($value => $options[$value]);
 $element->setAttrib('options', $sole_option);

4

フォームフィールドを無効にすると、フォームの送信時に送信されません。したがって、のreadonlyように機能するdisabledが値を送信する必要がある場合は、次のようにします。

要素の読み取り専用プロパティを変更した後。

$('select.readonly option:not(:selected)').attr('disabled',true);

$('select:not([readonly]) option').removeAttr('disabled');

4

tabindexを使用したソリューション。選択だけでなくテキスト入力でも機能します。

単に.disabledクラスを使用します。

CSS:

.disabled {
    pointer-events:none; /* No cursor */
    background-color: #eee; /* Gray background */
}

JS:

$(".disabled").attr("tabindex", "-1");

HTML:

<select class="disabled">
    <option value="0">0</option>
</select>

<input type="text" class="disabled" />

編集:Internet Explorerでは、次のJSも必要です。

$(document).on("mousedown", ".disabled", function (e) {
    e.preventDefault();
});

2

グラントワグナーズの提案に続き、これは、直接のonXXX属性の代わりにハンドラー関数でそれを行うjQueryスニペットです。

var readonlySelect = function(selector, makeReadonly) {

    $(selector).filter("select").each(function(i){
        var select = $(this);

        //remove any existing readonly handler
        if(this.readonlyFn) select.unbind("change", this.readonlyFn);
        if(this.readonlyIndex) this.readonlyIndex = null;

        if(makeReadonly) {
            this.readonlyIndex = this.selectedIndex;
            this.readonlyFn = function(){
                this.selectedIndex = this.readonlyIndex;
            };
            select.bind("change", this.readonlyFn);
        }
    });

};

2

私はjqueryでそれを解決しました:

      $("select.myselect").bind("focus", function(){
        if($(this).hasClass('readonly'))
        {
          $(this).blur();   
          return;
        }
      });

これは非常にうまく機能しましたが、マウスオーバーアニメーションにはクリック可能なドロップダウン矢印が表示されます。
Johncl、2011年

これはChrome 26では機能しません。選択はまだ完全に機能しています。
アンディ

しかし、IEでダブルクリックしてもリストは表示されます。とにかくそれを防ぐには?
user1995781 2013年

2

jquery validateを使用している場合は、以下を実行できます。問題なくdisabled属性を使用しました:

$(function(){
    $('#myform').validate({
        submitHandler:function(form){
            $('select').removeAttr('disabled');
            form.submit();
        }
    });
});

2

私が見つけたのは、プレーンなJavaScript(つまり、JQueryライブラリは不要)でうまく機能し、<select>タグのinnerHTMLを目的の単一の残りの値に変更することです。

前:

<select name='day' id='day'>
  <option>SUN</option>
  <option>MON</option>
  <option>TUE</option>
  <option>WED</option>
  <option>THU</option>
  <option>FRI</option>
  <option>SAT</option>
</select>

Javascriptの例:

document.getElementById('day').innerHTML = '<option>FRI</option>';

後:

<select name='day' id='day'>
  <option>FRI</option>
</select>

この方法では、視覚的な効果は変化せず、これは内でPOST / GETします<FORM>


1

選択自体ではなく、現在選択されているオプションを除くすべてのオプションを無効にすることができます。これにより、機能するドロップダウンのように見えますが、渡したいオプションのみが有効な選択です。


3
理論的には素晴らしいアイデアですが、IE8より前のIEでは無効なオプションはサポートされていません。tinyurl.com/yle4bto
scunliffe

1

HTMLソリューション:

<select onfocus="this.blur();">

JavaScriptのもの:

selectElement.addEventListener("focus", selectElement.blur, true); selectElement.attachEvent("focus", selectElement.blur); //thanks, IE

削除する:

selectElement.removeEventListener("focus", selectElement.blur, true); selectElement.detachEvent("focus", selectElement.blur); //thanks, IE

編集:追加された削除メソッド


@ButtleButkus javascriptのものは動作しますか?私はそれがブラウザー関連の問題である可能性があると思います。要素にtabindexを追加しようとしましたか
Kadmillos

1

単純に、フォームを送信する前に、disabled属性を削除してください。

    $('form').submit(function () {
        $("#Id_Unidade").attr("disabled", false);
    });

1
<select id="case_reason" name="case_reason" disabled="disabled">

disabled="disabled" ->データベースから値を取得し、フォームに表示します。 readonly="readonly" ->selectboxで値を変更できますが、値をデータベースに保存できませんでした。


間違っています。保存されています。「読み取り専用」プロパティはすべてのブラウザで処理されるわけではないため、信頼性が低いようです。
リッチー

0

選択ドロップダウンが誕生以来読み取り専用であり、まったく変更する必要がない場合、おそらく代わりに別のコントロールを使用する必要がありますか?単純な<div>(および非表示のフォームフィールド)または<input type="text">

追加:ドロップダウンが常に読み取り専用ではなく、JavaScriptを使用して有効化/無効化する場合でも、これは解決策です-DOMをその場で変更するだけです。


最初から読み取り専用ではありません。JavaScriptを使用して変更と更新を行っています。前のドロップダウンに特定の値がある場合、これは読み取り専用になります。
Jrgns 2008

次に、このドロップダウンをオンザフライでテキストボックスに置き換えることができますか?
Vilx- 2008

うん

0

以下は私のために働きました:

$('select[name=country]').attr("disabled", "disabled"); 

11
参考:無効化されたフォームフィールドは送信に含まれません。
mz_01

0

私は、選択ボックスを非表示にspanし、情報の価値のみを持つをその場所に表示することによって、それを管理しました。.readonlyクラスを無効にするイベントでは、.toVanish要素を削除して表示する必要もあり.toShowます。

 $( '.readonly' ).live( 'focus', function(e) {
                $( this ).attr( 'readonly', 'readonly' )
                if( $( this ).get(0).tagName == 'SELECT' ) {
                    $( this ).before( '<span class="toVanish readonly" style="border:1px solid; padding:5px">' 
                            + $( this ).find( 'option:selected' ).html() + '</span>' )
                    $( this ).addClass( 'toShow' )
                    $( this ).hide()
            }
    });

0

IEでは、ダブルクリックすることでonfocus => onblurアプローチを打ち負かすことができました。しかし、値を覚えてからonchangeイベントでそれを復元すると、その問題を処理できるようです。

<select onfocus="this.oldvalue=this.value;this.blur();" onchange="this.value=this.oldvalue;">
....
</select>

javascript変数を使用すると、expandoプロパティなしで同様のことができます。


0

次に、カスタムjQuery関数を使用して機能を実現しようとする試みを示します(ここで説明したとおり)。

$(function(){

 $.prototype.toggleDisable = function(flag) {
    // prepare some values
    var selectId = $(this).attr('id');
    var hiddenId = selectId + 'hidden';
    if (flag) {
      // disable the select - however this will not submit the value of the select
      // a new hidden form element will be created below to compensate for the 
      // non-submitted select value 
      $(this).attr('disabled', true);

      // gather attributes
      var selectVal = $(this).val();
      var selectName = $(this).attr('name');

      // creates a hidden form element to submit the value of the disabled select
      $(this).parents('form').append($('<input></input>').
        attr('type', 'hidden').
        attr('id', hiddenId).
        attr('name', selectName).
        val(selectVal) );
    } else {
      // remove the newly-created hidden form element
      $(this).parents('form').remove(hiddenId);
      // enable back the element
      $(this).removeAttr('disabled');
    }
  }

  // Usage
  // $('#some_select_element').toggleDisable(true);
  // $('#some_select_element').toggleDisable(false);

});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.